1 package org
.argeo
.cms
.internal
.http
;
3 import java
.io
.IOException
;
4 import java
.nio
.file
.Files
;
5 import java
.nio
.file
.Path
;
6 import java
.util
.Properties
;
8 import javax
.jcr
.Repository
;
9 import javax
.servlet
.ServletException
;
10 import javax
.servlet
.http
.HttpServletRequest
;
11 import javax
.servlet
.http
.HttpServletResponse
;
13 import org
.apache
.commons
.logging
.Log
;
14 import org
.apache
.commons
.logging
.LogFactory
;
15 import org
.apache
.jackrabbit
.server
.SessionProvider
;
16 import org
.apache
.jackrabbit
.server
.remoting
.davex
.JcrRemotingServlet
;
17 import org
.apache
.jackrabbit
.webdav
.simple
.SimpleWebdavServlet
;
18 import org
.argeo
.cms
.CmsException
;
19 import org
.argeo
.cms
.internal
.kernel
.KernelConstants
;
20 import org
.argeo
.node
.NodeConstants
;
21 import org
.osgi
.framework
.BundleContext
;
22 import org
.osgi
.framework
.FrameworkUtil
;
23 import org
.osgi
.framework
.ServiceReference
;
24 import org
.osgi
.service
.http
.HttpService
;
25 import org
.osgi
.service
.http
.NamespaceException
;
26 import org
.osgi
.util
.tracker
.ServiceTracker
;
29 * Intercepts and enriches http access, mainly focusing on security and
32 public class NodeHttp
implements KernelConstants
{
33 private final static Log log
= LogFactory
.getLog(NodeHttp
.class);
36 // private final RootFilter rootFilter;
38 // private final DoSFilter dosFilter;
39 // private final QoSFilter qosFilter;
41 private final BundleContext bc
= FrameworkUtil
.getBundle(getClass()).getBundleContext();
43 private ServiceTracker
<Repository
, Repository
> repositories
;
44 private final ServiceTracker
<HttpService
, HttpService
> httpServiceTracker
;
47 // rootFilter = new RootFilter();
48 // dosFilter = new CustomDosFilter();
49 // qosFilter = new QoSFilter();
51 httpServiceTracker
= new PrepareHttpStc();
52 httpServiceTracker
.open();
55 // class CustomDosFilter extends DoSFilter {
57 // protected String extractUserId(ServletRequest request) {
58 // HttpSession httpSession = ((HttpServletRequest) request)
60 // if (isSessionAuthenticated(httpSession)) {
61 // String userId = ((SecurityContext) httpSession
62 // .getAttribute(SPRING_SECURITY_CONTEXT_KEY))
63 // .getAuthentication().getName();
66 // return super.extractUserId(request);
71 public void destroy() {
75 void registerRepositoryServlets(HttpService httpService
, String alias
, Repository repository
) {
76 if (httpService
== null)
77 throw new CmsException("No HTTP service available");
79 registerWebdavServlet(httpService
, alias
, repository
);
80 registerRemotingServlet(httpService
, alias
, repository
);
81 if (NodeConstants
.HOME
.equals(alias
))
82 registerFilesServlet(httpService
, alias
, repository
);
83 if (log
.isDebugEnabled())
84 log
.debug("Registered servlets for repository '" + alias
+ "'");
85 } catch (Exception e
) {
86 throw new CmsException("Could not register servlets for repository '" + alias
+ "'", e
);
90 void unregisterRepositoryServlets(HttpService httpService
, String alias
) {
91 if (httpService
== null)
94 httpService
.unregister(webdavPath(alias
));
95 httpService
.unregister(remotingPath(alias
));
96 if (NodeConstants
.HOME
.equals(alias
))
97 httpService
.unregister(filesPath(alias
));
98 if (log
.isDebugEnabled())
99 log
.debug("Unregistered servlets for repository '" + alias
+ "'");
100 } catch (Exception e
) {
101 log
.error("Could not unregister servlets for repository '" + alias
+ "'", e
);
105 void registerWebdavServlet(HttpService httpService
, String alias
, Repository repository
)
106 throws NamespaceException
, ServletException
{
107 // WebdavServlet webdavServlet = new WebdavServlet(repository, new
108 // OpenInViewSessionProvider(alias));
109 WebdavServlet webdavServlet
= new WebdavServlet(repository
, new CmsSessionProvider(alias
));
110 String path
= webdavPath(alias
);
111 Properties ip
= new Properties();
112 ip
.setProperty(WebdavServlet
.INIT_PARAM_RESOURCE_CONFIG
, HttpUtils
.WEBDAV_CONFIG
);
113 ip
.setProperty(WebdavServlet
.INIT_PARAM_RESOURCE_PATH_PREFIX
, path
);
114 httpService
.registerServlet(path
, webdavServlet
, ip
, new DataHttpContext());
117 void registerFilesServlet(HttpService httpService
, String alias
, Repository repository
)
118 throws NamespaceException
, ServletException
{
119 WebdavServlet filesServlet
= new WebdavServlet(repository
, new CmsSessionProvider(alias
));
120 String path
= filesPath(alias
);
121 Properties ip
= new Properties();
122 ip
.setProperty(WebdavServlet
.INIT_PARAM_RESOURCE_CONFIG
, HttpUtils
.WEBDAV_CONFIG
);
123 ip
.setProperty(WebdavServlet
.INIT_PARAM_RESOURCE_PATH_PREFIX
, path
);
124 httpService
.registerServlet(path
, filesServlet
, ip
, new PrivateHttpContext());
127 void registerRemotingServlet(HttpService httpService
, String alias
, Repository repository
)
128 throws NamespaceException
, ServletException
{
129 RemotingServlet remotingServlet
= new RemotingServlet(repository
, new CmsSessionProvider(alias
));
130 String path
= remotingPath(alias
);
131 Properties ip
= new Properties();
132 ip
.setProperty(JcrRemotingServlet
.INIT_PARAM_RESOURCE_PATH_PREFIX
, path
);
134 // Looks like a bug in Jackrabbit remoting init
137 tmpDir
= Files
.createTempDirectory("remoting_" + alias
);
138 } catch (IOException e
) {
139 throw new CmsException("Cannot create temp directory for remoting servlet", e
);
141 ip
.setProperty(RemotingServlet
.INIT_PARAM_HOME
, tmpDir
.toString());
142 ip
.setProperty(RemotingServlet
.INIT_PARAM_TMP_DIRECTORY
, "remoting_" + alias
);
143 ip
.setProperty(RemotingServlet
.INIT_PARAM_PROTECTED_HANDLERS_CONFIG
, HttpUtils
.DEFAULT_PROTECTED_HANDLERS
);
144 ip
.setProperty(RemotingServlet
.INIT_PARAM_CREATE_ABSOLUTE_URI
, "false");
145 httpService
.registerServlet(path
, remotingServlet
, ip
, new PrivateHttpContext());
148 private String
webdavPath(String alias
) {
149 return NodeConstants
.PATH_DATA
+ "/" + alias
;
152 private String
remotingPath(String alias
) {
153 return NodeConstants
.PATH_JCR
+ "/" + alias
;
156 private String
filesPath(String alias
) {
157 return NodeConstants
.PATH_FILES
;
160 // private Subject subjectFromRequest(HttpServletRequest request,
161 // HttpServletResponse response) {
162 // Authorization authorization = (Authorization)
163 // request.getAttribute(HttpContext.AUTHORIZATION);
164 // if (authorization == null)
165 // throw new CmsException("Not authenticated");
167 // LoginContext lc = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER,
168 // new HttpRequestCallbackHandler(request, response));
170 // return lc.getSubject();
171 // } catch (LoginException e) {
172 // throw new CmsException("Cannot login", e);
176 private class RepositoriesStc
extends ServiceTracker
<Repository
, Repository
> {
177 private final HttpService httpService
;
179 public RepositoriesStc(HttpService httpService
) {
180 super(bc
, Repository
.class, null);
181 this.httpService
= httpService
;
185 public Repository
addingService(ServiceReference
<Repository
> reference
) {
186 Repository repository
= bc
.getService(reference
);
187 Object jcrRepoAlias
= reference
.getProperty(NodeConstants
.CN
);
188 if (jcrRepoAlias
!= null) {
189 String alias
= jcrRepoAlias
.toString();
190 registerRepositoryServlets(httpService
, alias
, repository
);
196 public void modifiedService(ServiceReference
<Repository
> reference
, Repository service
) {
200 public void removedService(ServiceReference
<Repository
> reference
, Repository service
) {
201 Object jcrRepoAlias
= reference
.getProperty(NodeConstants
.CN
);
202 if (jcrRepoAlias
!= null) {
203 String alias
= jcrRepoAlias
.toString();
204 unregisterRepositoryServlets(httpService
, alias
);
209 private class PrepareHttpStc
extends ServiceTracker
<HttpService
, HttpService
> {
210 // private DataHttp dataHttp;
211 // private NodeHttp nodeHttp;
213 public PrepareHttpStc() {
214 super(bc
, HttpService
.class, null);
218 public HttpService
addingService(ServiceReference
<HttpService
> reference
) {
219 HttpService httpService
= addHttpService(reference
);
224 public void removedService(ServiceReference
<HttpService
> reference
, HttpService service
) {
225 // if (dataHttp != null)
226 // dataHttp.destroy();
228 // if (nodeHttp != null)
229 // nodeHttp.destroy();
232 repositories
.close();
236 private HttpService
addHttpService(ServiceReference
<HttpService
> sr
) {
237 HttpService httpService
= bc
.getService(sr
);
238 // TODO find constants
239 Object httpPort
= sr
.getProperty("http.port");
240 Object httpsPort
= sr
.getProperty("https.port");
243 httpService
.registerServlet("/!", new LinkServlet(), null, null);
244 httpService
.registerServlet("/robots.txt", new RobotServlet(), null, null);
245 } catch (Exception e
) {
246 throw new CmsException("Cannot register filters", e
);
248 // track repositories
249 if (repositories
!= null)
250 throw new CmsException("An http service is already configured");
251 repositories
= new RepositoriesStc(httpService
);
253 log
.info(httpPortsMsg(httpPort
, httpsPort
));
254 // httpAvailable = true;
257 bc
.registerService(NodeHttp
.class, NodeHttp
.this, null);
261 private String
httpPortsMsg(Object httpPort
, Object httpsPort
) {
262 return "HTTP " + httpPort
+ (httpsPort
!= null ?
" - HTTPS " + httpsPort
: "");
266 private class WebdavServlet
extends SimpleWebdavServlet
{
267 private static final long serialVersionUID
= -4687354117811443881L;
268 private final Repository repository
;
270 public WebdavServlet(Repository repository
, SessionProvider sessionProvider
) {
271 this.repository
= repository
;
272 setSessionProvider(sessionProvider
);
275 public Repository
getRepository() {
280 protected void service(final HttpServletRequest request
, final HttpServletResponse response
)
281 throws ServletException
, IOException
{
282 WebdavServlet
.super.service(request
, response
);
284 // Subject subject = subjectFromRequest(request);
285 // // TODO make it stronger, with eTags.
286 // // if (CurrentUser.isAnonymous(subject) &&
287 // // request.getMethod().equals("GET")) {
288 // // response.setHeader("Cache-Control", "no-transform, public,
289 // // max-age=300, s-maxage=900");
292 // Subject.doAs(subject, new PrivilegedExceptionAction<Void>() {
294 // public Void run() throws Exception {
295 // WebdavServlet.super.service(request, response);
299 // } catch (PrivilegedActionException e) {
300 // throw new CmsException("Cannot process webdav request",
301 // e.getException());
306 private class RemotingServlet
extends JcrRemotingServlet
{
307 private static final long serialVersionUID
= 4605238259548058883L;
308 private final Repository repository
;
309 private final SessionProvider sessionProvider
;
311 public RemotingServlet(Repository repository
, SessionProvider sessionProvider
) {
312 this.repository
= repository
;
313 this.sessionProvider
= sessionProvider
;
317 protected Repository
getRepository() {
322 protected SessionProvider
getSessionProvider() {
323 return sessionProvider
;
327 protected void service(final HttpServletRequest request
, final HttpServletResponse response
)
328 throws ServletException
, IOException
{
330 // Subject subject = subjectFromRequest(request, response);
331 // Subject.doAs(subject, new PrivilegedExceptionAction<Void>() {
333 // public Void run() throws Exception {
334 RemotingServlet
.super.service(request
, response
);
338 // } catch (PrivilegedActionException e) {
339 // throw new CmsException("Cannot process JCR remoting request",
340 // e.getException());