]> git.argeo.org Git - lgpl/argeo-commons.git/blob - cms/jcr/CmsJcrUtils.java
Prepare next development cycle
[lgpl/argeo-commons.git] / cms / jcr / CmsJcrUtils.java
1 package org.argeo.cms.jcr;
2
3 import java.security.PrivilegedAction;
4 import java.util.HashMap;
5 import java.util.Map;
6
7 import javax.jcr.NoSuchWorkspaceException;
8 import javax.jcr.Node;
9 import javax.jcr.Property;
10 import javax.jcr.Repository;
11 import javax.jcr.RepositoryException;
12 import javax.jcr.RepositoryFactory;
13 import javax.jcr.Session;
14 import javax.naming.InvalidNameException;
15 import javax.naming.ldap.LdapName;
16 import javax.security.auth.AuthPermission;
17 import javax.security.auth.Subject;
18 import javax.security.auth.login.LoginContext;
19 import javax.security.auth.login.LoginException;
20
21 import org.argeo.api.NodeConstants;
22
23 /** Utilities related to Argeo model in JCR */
24 public class CmsJcrUtils {
25 /**
26 * Wraps the call to the repository factory based on parameter
27 * {@link NodeConstants#CN} in order to simplify it and protect against future
28 * API changes.
29 */
30 public static Repository getRepositoryByAlias(RepositoryFactory repositoryFactory, String alias) {
31 try {
32 Map<String, String> parameters = new HashMap<String, String>();
33 parameters.put(NodeConstants.CN, alias);
34 return repositoryFactory.getRepository(parameters);
35 } catch (RepositoryException e) {
36 throw new RuntimeException("Unexpected exception when trying to retrieve repository with alias " + alias,
37 e);
38 }
39 }
40
41 /**
42 * Wraps the call to the repository factory based on parameter
43 * {@link NodeConstants#LABELED_URI} in order to simplify it and protect against
44 * future API changes.
45 */
46 public static Repository getRepositoryByUri(RepositoryFactory repositoryFactory, String uri) {
47 return getRepositoryByUri(repositoryFactory, uri, null);
48 }
49
50 /**
51 * Wraps the call to the repository factory based on parameter
52 * {@link NodeConstants#LABELED_URI} in order to simplify it and protect against
53 * future API changes.
54 */
55 public static Repository getRepositoryByUri(RepositoryFactory repositoryFactory, String uri, String alias) {
56 try {
57 Map<String, String> parameters = new HashMap<String, String>();
58 parameters.put(NodeConstants.LABELED_URI, uri);
59 if (alias != null)
60 parameters.put(NodeConstants.CN, alias);
61 return repositoryFactory.getRepository(parameters);
62 } catch (RepositoryException e) {
63 throw new RuntimeException("Unexpected exception when trying to retrieve repository with uri " + uri, e);
64 }
65 }
66
67 /**
68 * Returns the home node of the user or null if none was found.
69 *
70 * @param session the session to use in order to perform the search, this can
71 * be a session with a different user ID than the one searched,
72 * typically when a system or admin session is used.
73 * @param username the username of the user
74 */
75 public static Node getUserHome(Session session, String username) {
76 // try {
77 // QueryObjectModelFactory qomf = session.getWorkspace().getQueryManager().getQOMFactory();
78 // Selector sel = qomf.selector(NodeTypes.NODE_USER_HOME, "sel");
79 // DynamicOperand dop = qomf.propertyValue(sel.getSelectorName(), NodeNames.LDAP_UID);
80 // StaticOperand sop = qomf.literal(session.getValueFactory().createValue(username));
81 // Constraint constraint = qomf.comparison(dop, QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, sop);
82 // Query query = qomf.createQuery(sel, constraint, null, null);
83 // return querySingleNode(query);
84 // } catch (RepositoryException e) {
85 // throw new RuntimeException("Cannot find home for user " + username, e);
86 // }
87
88 try {
89 checkUserWorkspace(session, username);
90 String homePath = getHomePath(username);
91 if (session.itemExists(homePath))
92 return session.getNode(homePath);
93 // legacy
94 homePath = "/home/" + username;
95 if (session.itemExists(homePath))
96 return session.getNode(homePath);
97 return null;
98 } catch (RepositoryException e) {
99 throw new RuntimeException("Cannot find home for user " + username, e);
100 }
101 }
102
103 private static String getHomePath(String username) {
104 LdapName dn;
105 try {
106 dn = new LdapName(username);
107 } catch (InvalidNameException e) {
108 throw new IllegalArgumentException("Invalid name " + username, e);
109 }
110 String userId = dn.getRdn(dn.size() - 1).getValue().toString();
111 return '/' + userId;
112 }
113
114 private static void checkUserWorkspace(Session session, String username) {
115 String workspaceName = session.getWorkspace().getName();
116 if (!NodeConstants.HOME_WORKSPACE.equals(workspaceName))
117 throw new IllegalArgumentException(workspaceName + " is not the home workspace for user " + username);
118 }
119
120 /**
121 * Returns the home node of the user or null if none was found.
122 *
123 * @param session the session to use in order to perform the search, this can
124 * be a session with a different user ID than the one searched,
125 * typically when a system or admin session is used.
126 * @param groupname the name of the group
127 */
128 public static Node getGroupHome(Session session, String groupname) {
129 // try {
130 // QueryObjectModelFactory qomf = session.getWorkspace().getQueryManager().getQOMFactory();
131 // Selector sel = qomf.selector(NodeTypes.NODE_GROUP_HOME, "sel");
132 // DynamicOperand dop = qomf.propertyValue(sel.getSelectorName(), NodeNames.LDAP_CN);
133 // StaticOperand sop = qomf.literal(session.getValueFactory().createValue(cn));
134 // Constraint constraint = qomf.comparison(dop, QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, sop);
135 // Query query = qomf.createQuery(sel, constraint, null, null);
136 // return querySingleNode(query);
137 // } catch (RepositoryException e) {
138 // throw new RuntimeException("Cannot find home for group " + cn, e);
139 // }
140
141 try {
142 checkGroupWorkspace(session, groupname);
143 String homePath = getGroupPath(groupname);
144 if (session.itemExists(homePath))
145 return session.getNode(homePath);
146 // legacy
147 homePath = "/groups/" + groupname;
148 if (session.itemExists(homePath))
149 return session.getNode(homePath);
150 return null;
151 } catch (RepositoryException e) {
152 throw new RuntimeException("Cannot find home for group " + groupname, e);
153 }
154
155 }
156
157 private static String getGroupPath(String groupname) {
158 String cn;
159 try {
160 LdapName dn = new LdapName(groupname);
161 cn = dn.getRdn(dn.size() - 1).getValue().toString();
162 } catch (InvalidNameException e) {
163 cn = groupname;
164 }
165 return '/' + cn;
166 }
167
168 private static void checkGroupWorkspace(Session session, String groupname) {
169 String workspaceName = session.getWorkspace().getName();
170 if (!NodeConstants.SRV_WORKSPACE.equals(workspaceName))
171 throw new IllegalArgumentException(workspaceName + " is not the group workspace for group " + groupname);
172 }
173
174 /**
175 * Queries one single node.
176 *
177 * @return one single node or null if none was found
178 * @throws ArgeoJcrException if more than one node was found
179 */
180 // private static Node querySingleNode(Query query) {
181 // NodeIterator nodeIterator;
182 // try {
183 // QueryResult queryResult = query.execute();
184 // nodeIterator = queryResult.getNodes();
185 // } catch (RepositoryException e) {
186 // throw new RuntimeException("Cannot execute query " + query, e);
187 // }
188 // Node node;
189 // if (nodeIterator.hasNext())
190 // node = nodeIterator.nextNode();
191 // else
192 // return null;
193 //
194 // if (nodeIterator.hasNext())
195 // throw new RuntimeException("Query returned more than one node.");
196 // return node;
197 // }
198
199 /** Returns the home node of the session user or null if none was found. */
200 public static Node getUserHome(Session session) {
201 String userID = session.getUserID();
202 return getUserHome(session, userID);
203 }
204
205 /** Whether this node is the home of the user of the underlying session. */
206 public static boolean isUserHome(Node node) {
207 try {
208 String userID = node.getSession().getUserID();
209 return node.hasProperty(Property.JCR_ID) && node.getProperty(Property.JCR_ID).getString().equals(userID);
210 } catch (RepositoryException e) {
211 throw new IllegalStateException(e);
212 }
213 }
214
215 /**
216 * Translate the path to this node into a path containing the name of the
217 * repository and the name of the workspace.
218 */
219 public static String getDataPath(String cn, Node node) {
220 assert node != null;
221 StringBuilder buf = new StringBuilder(NodeConstants.PATH_DATA);
222 try {
223 return buf.append('/').append(cn).append('/').append(node.getSession().getWorkspace().getName())
224 .append(node.getPath()).toString();
225 } catch (RepositoryException e) {
226 throw new IllegalStateException("Cannot get data path for " + node + " in repository " + cn, e);
227 }
228 }
229
230 /**
231 * Translate the path to this node into a path containing the name of the
232 * repository and the name of the workspace.
233 */
234 public static String getDataPath(Node node) {
235 return getDataPath(NodeConstants.NODE, node);
236 }
237
238 /**
239 * Open a JCR session with full read/write rights on the data, as
240 * {@link NodeConstants#ROLE_USER_ADMIN}, using the
241 * {@link NodeConstants#LOGIN_CONTEXT_DATA_ADMIN} login context. For security
242 * hardened deployement, use {@link AuthPermission} on this login context.
243 */
244 public static Session openDataAdminSession(Repository repository, String workspaceName) {
245 ClassLoader currentCl = Thread.currentThread().getContextClassLoader();
246 LoginContext loginContext;
247 try {
248 loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_DATA_ADMIN);
249 loginContext.login();
250 } catch (LoginException e1) {
251 throw new RuntimeException("Could not login as data admin", e1);
252 } finally {
253 Thread.currentThread().setContextClassLoader(currentCl);
254 }
255 return Subject.doAs(loginContext.getSubject(), new PrivilegedAction<Session>() {
256
257 @Override
258 public Session run() {
259 try {
260 return repository.login(workspaceName);
261 } catch (NoSuchWorkspaceException e) {
262 throw new IllegalArgumentException("No workspace " + workspaceName + " available", e);
263 } catch (RepositoryException e) {
264 throw new RuntimeException("Cannot open data admin session", e);
265 }
266 }
267
268 });
269 }
270
271 /** Singleton. */
272 private CmsJcrUtils() {
273 }
274
275 }