]> git.argeo.org Git - lgpl/argeo-commons.git/blob - server/runtime/org.argeo.server.jackrabbit/src/main/java/org/argeo/jackrabbit/remote/SimpleSessionProvider.java
Refactor JCR utils and home usage
[lgpl/argeo-commons.git] / server / runtime / org.argeo.server.jackrabbit / src / main / java / org / argeo / jackrabbit / remote / SimpleSessionProvider.java
1 /*
2 * Copyright (C) 2007-2012 Mathieu Baudier
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 org.argeo.jackrabbit.remote;
17
18 import java.io.Serializable;
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.Map;
25
26 import javax.jcr.LoginException;
27 import javax.jcr.Node;
28 import javax.jcr.Repository;
29 import javax.jcr.RepositoryException;
30 import javax.jcr.Session;
31 import javax.jcr.Value;
32 import javax.servlet.ServletException;
33 import javax.servlet.http.HttpServletRequest;
34
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37 import org.apache.jackrabbit.api.JackrabbitSession;
38 import org.apache.jackrabbit.api.security.user.Group;
39 import org.apache.jackrabbit.api.security.user.User;
40 import org.apache.jackrabbit.api.security.user.UserManager;
41 import org.apache.jackrabbit.server.SessionProvider;
42 import org.argeo.ArgeoException;
43 import org.argeo.jcr.ArgeoNames;
44 import org.argeo.jcr.JcrUtils;
45 import org.argeo.jcr.UserJcrUtils;
46
47 /**
48 * Implements an open session in view patter: a new JCR session is created for
49 * each request
50 */
51 public class SimpleSessionProvider implements SessionProvider, Serializable {
52 private static final long serialVersionUID = 2270957712453841368L;
53
54 private final static Log log = LogFactory
55 .getLog(SimpleSessionProvider.class);
56
57 private transient Map<String, Session> sessions;
58
59 private Boolean openSessionInView = true;
60
61 private String securityWorkspace = "security";
62
63 public Session getSession(HttpServletRequest request, Repository rep,
64 String workspace) throws LoginException, ServletException,
65 RepositoryException {
66
67 if (openSessionInView) {
68 JackrabbitSession session = (JackrabbitSession) rep
69 .login(workspace);
70 if (session.getWorkspace().getName().equals(securityWorkspace))
71 writeRemoteRoles(session);
72 return session;
73 } else {
74 // since sessions is transient it can't be restored from the session
75 if (sessions == null)
76 sessions = Collections
77 .synchronizedMap(new HashMap<String, Session>());
78
79 if (!sessions.containsKey(workspace)) {
80 try {
81 JackrabbitSession session = (JackrabbitSession) rep.login(
82 null, workspace);
83 if (session.getWorkspace().getName()
84 .equals(securityWorkspace))
85 writeRemoteRoles(session);
86 if (log.isTraceEnabled())
87 log.trace("User " + session.getUserID()
88 + " logged into " + request.getServletPath());
89 sessions.put(workspace, session);
90 return session;
91 } catch (Exception e) {
92 throw new ArgeoException("Cannot open session", e);
93 }
94 } else {
95 Session session = sessions.get(workspace);
96 if (!session.isLive()) {
97 sessions.remove(workspace);
98 session = rep.login(null, workspace);
99 sessions.put(workspace, session);
100 }
101 return session;
102 }
103 }
104 }
105
106 protected void writeRemoteRoles(JackrabbitSession session)
107 throws RepositoryException {
108 // retrieve roles
109 String userId = session.getUserID();
110 UserManager userManager = session.getUserManager();
111 User user = (User) userManager.getAuthorizable(userId);
112 if (user == null) {
113 // anonymous
114 return;
115 }
116 List<String> userGroupIds = new ArrayList<String>();
117 if (user != null)
118 for (Iterator<Group> it = user.memberOf(); it.hasNext();)
119 userGroupIds.add(it.next().getID());
120
121 // write roles if needed
122 Node userProfile = UserJcrUtils.getUserHome(session).getNode(
123 ArgeoNames.ARGEO_PROFILE);
124 boolean writeRoles = false;
125 if (userProfile.hasProperty(ArgeoNames.ARGEO_REMOTE_ROLES)) {
126 Value[] roles = userProfile.getProperty(
127 ArgeoNames.ARGEO_REMOTE_ROLES).getValues();
128 if (roles.length != userGroupIds.size())
129 writeRoles = true;
130 else
131 for (int i = 0; i < roles.length; i++)
132 if (!roles[i].getString().equals(userGroupIds.get(i)))
133 writeRoles = true;
134 } else
135 writeRoles = true;
136
137 if (writeRoles) {
138 session.getWorkspace().getVersionManager()
139 .checkout(userProfile.getPath());
140 String[] roleIds = userGroupIds.toArray(new String[userGroupIds
141 .size()]);
142 userProfile.setProperty(ArgeoNames.ARGEO_REMOTE_ROLES, roleIds);
143 JcrUtils.updateLastModified(userProfile);
144 session.save();
145 session.getWorkspace().getVersionManager()
146 .checkin(userProfile.getPath());
147 }
148
149 }
150
151 public void releaseSession(Session session) {
152 if (log.isTraceEnabled())
153 log.trace("Releasing JCR session " + session);
154 if (openSessionInView) {
155 if (session.isLive()) {
156 session.logout();
157 if (log.isTraceEnabled())
158 log.trace("Logged out remote JCR session " + session);
159 }
160 }
161 }
162
163 public void init() {
164 }
165
166 public void destroy() {
167 if (sessions != null)
168 for (String workspace : sessions.keySet()) {
169 Session session = sessions.get(workspace);
170 if (session.isLive()) {
171 session.logout();
172 if (log.isDebugEnabled())
173 log.debug("Logged out remote JCR session " + session);
174 }
175 }
176 }
177
178 /**
179 * If set to true a new session will be created each time (the default),
180 * otherwise a single session is cached by workspace and the object should
181 * be of scope session (not supported)
182 */
183 public void setOpenSessionInView(Boolean openSessionInView) {
184 this.openSessionInView = openSessionInView;
185 }
186
187 public void setSecurityWorkspace(String securityWorkspace) {
188 this.securityWorkspace = securityWorkspace;
189 }
190
191 }