1 package org
.argeo
.cms
.jcr
;
3 import java
.security
.PrivilegedAction
;
4 import java
.util
.HashMap
;
7 import javax
.jcr
.NoSuchWorkspaceException
;
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
;
21 import org
.argeo
.api
.cms
.CmsAuth
;
22 import org
.argeo
.api
.cms
.CmsConstants
;
24 /** Utilities related to Argeo model in JCR */
25 public class CmsJcrUtils
{
27 * Wraps the call to the repository factory based on parameter
28 * {@link CmsConstants#CN} in order to simplify it and protect against future
31 public static Repository
getRepositoryByAlias(RepositoryFactory repositoryFactory
, String alias
) {
33 Map
<String
, String
> parameters
= new HashMap
<String
, String
>();
34 parameters
.put(CmsConstants
.CN
, alias
);
35 return repositoryFactory
.getRepository(parameters
);
36 } catch (RepositoryException e
) {
37 throw new RuntimeException("Unexpected exception when trying to retrieve repository with alias " + alias
,
43 * Wraps the call to the repository factory based on parameter
44 * {@link CmsConstants#LABELED_URI} in order to simplify it and protect against
47 public static Repository
getRepositoryByUri(RepositoryFactory repositoryFactory
, String uri
) {
48 return getRepositoryByUri(repositoryFactory
, uri
, null);
52 * Wraps the call to the repository factory based on parameter
53 * {@link CmsConstants#LABELED_URI} in order to simplify it and protect against
56 public static Repository
getRepositoryByUri(RepositoryFactory repositoryFactory
, String uri
, String alias
) {
58 Map
<String
, String
> parameters
= new HashMap
<String
, String
>();
59 parameters
.put(CmsConstants
.LABELED_URI
, uri
);
61 parameters
.put(CmsConstants
.CN
, alias
);
62 return repositoryFactory
.getRepository(parameters
);
63 } catch (RepositoryException e
) {
64 throw new RuntimeException("Unexpected exception when trying to retrieve repository with uri " + uri
, e
);
69 * Returns the home node of the user or null if none was found.
71 * @param session the session to use in order to perform the search, this can
72 * be a session with a different user ID than the one searched,
73 * typically when a system or admin session is used.
74 * @param username the username of the user
76 public static Node
getUserHome(Session session
, String username
) {
78 // QueryObjectModelFactory qomf = session.getWorkspace().getQueryManager().getQOMFactory();
79 // Selector sel = qomf.selector(NodeTypes.NODE_USER_HOME, "sel");
80 // DynamicOperand dop = qomf.propertyValue(sel.getSelectorName(), NodeNames.LDAP_UID);
81 // StaticOperand sop = qomf.literal(session.getValueFactory().createValue(username));
82 // Constraint constraint = qomf.comparison(dop, QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, sop);
83 // Query query = qomf.createQuery(sel, constraint, null, null);
84 // return querySingleNode(query);
85 // } catch (RepositoryException e) {
86 // throw new RuntimeException("Cannot find home for user " + username, e);
90 checkUserWorkspace(session
, username
);
91 String homePath
= getHomePath(username
);
92 if (session
.itemExists(homePath
))
93 return session
.getNode(homePath
);
95 homePath
= "/home/" + username
;
96 if (session
.itemExists(homePath
))
97 return session
.getNode(homePath
);
99 } catch (RepositoryException e
) {
100 throw new RuntimeException("Cannot find home for user " + username
, e
);
104 private static String
getHomePath(String username
) {
107 dn
= new LdapName(username
);
108 } catch (InvalidNameException e
) {
109 throw new IllegalArgumentException("Invalid name " + username
, e
);
111 String userId
= dn
.getRdn(dn
.size() - 1).getValue().toString();
115 private static void checkUserWorkspace(Session session
, String username
) {
116 String workspaceName
= session
.getWorkspace().getName();
117 if (!CmsConstants
.HOME_WORKSPACE
.equals(workspaceName
))
118 throw new IllegalArgumentException(workspaceName
+ " is not the home workspace for user " + username
);
122 * Returns the home node of the user or null if none was found.
124 * @param session the session to use in order to perform the search, this can
125 * be a session with a different user ID than the one searched,
126 * typically when a system or admin session is used.
127 * @param groupname the name of the group
129 public static Node
getGroupHome(Session session
, String groupname
) {
131 // QueryObjectModelFactory qomf = session.getWorkspace().getQueryManager().getQOMFactory();
132 // Selector sel = qomf.selector(NodeTypes.NODE_GROUP_HOME, "sel");
133 // DynamicOperand dop = qomf.propertyValue(sel.getSelectorName(), NodeNames.LDAP_CN);
134 // StaticOperand sop = qomf.literal(session.getValueFactory().createValue(cn));
135 // Constraint constraint = qomf.comparison(dop, QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, sop);
136 // Query query = qomf.createQuery(sel, constraint, null, null);
137 // return querySingleNode(query);
138 // } catch (RepositoryException e) {
139 // throw new RuntimeException("Cannot find home for group " + cn, e);
143 checkGroupWorkspace(session
, groupname
);
144 String homePath
= getGroupPath(groupname
);
145 if (session
.itemExists(homePath
))
146 return session
.getNode(homePath
);
148 homePath
= "/groups/" + groupname
;
149 if (session
.itemExists(homePath
))
150 return session
.getNode(homePath
);
152 } catch (RepositoryException e
) {
153 throw new RuntimeException("Cannot find home for group " + groupname
, e
);
158 private static String
getGroupPath(String groupname
) {
161 LdapName dn
= new LdapName(groupname
);
162 cn
= dn
.getRdn(dn
.size() - 1).getValue().toString();
163 } catch (InvalidNameException e
) {
169 private static void checkGroupWorkspace(Session session
, String groupname
) {
170 String workspaceName
= session
.getWorkspace().getName();
171 if (!CmsConstants
.SRV_WORKSPACE
.equals(workspaceName
))
172 throw new IllegalArgumentException(workspaceName
+ " is not the group workspace for group " + groupname
);
176 * Queries one single node.
178 * @return one single node or null if none was found
179 * @throws ArgeoJcrException if more than one node was found
181 // private static Node querySingleNode(Query query) {
182 // NodeIterator nodeIterator;
184 // QueryResult queryResult = query.execute();
185 // nodeIterator = queryResult.getNodes();
186 // } catch (RepositoryException e) {
187 // throw new RuntimeException("Cannot execute query " + query, e);
190 // if (nodeIterator.hasNext())
191 // node = nodeIterator.nextNode();
195 // if (nodeIterator.hasNext())
196 // throw new RuntimeException("Query returned more than one node.");
200 /** Returns the home node of the session user or null if none was found. */
201 public static Node
getUserHome(Session session
) {
202 String userID
= session
.getUserID();
203 return getUserHome(session
, userID
);
206 /** Whether this node is the home of the user of the underlying session. */
207 public static boolean isUserHome(Node node
) {
209 String userID
= node
.getSession().getUserID();
210 return node
.hasProperty(Property
.JCR_ID
) && node
.getProperty(Property
.JCR_ID
).getString().equals(userID
);
211 } catch (RepositoryException e
) {
212 throw new IllegalStateException(e
);
217 * Translate the path to this node into a path containing the name of the
218 * repository and the name of the workspace.
220 public static String
getDataPath(String cn
, Node node
) {
222 StringBuilder buf
= new StringBuilder(CmsConstants
.PATH_DATA
);
224 return buf
.append('/').append(cn
).append('/').append(node
.getSession().getWorkspace().getName())
225 .append(node
.getPath()).toString();
226 } catch (RepositoryException e
) {
227 throw new IllegalStateException("Cannot get data path for " + node
+ " in repository " + cn
, e
);
232 * Translate the path to this node into a path containing the name of the
233 * repository and the name of the workspace.
235 public static String
getDataPath(Node node
) {
236 return getDataPath(CmsConstants
.NODE
, node
);
240 * Open a JCR session with full read/write rights on the data, as
241 * {@link CmsConstants#ROLE_USER_ADMIN}, using the
242 * {@link CmsAuth#LOGIN_CONTEXT_DATA_ADMIN} login context. For security
243 * hardened deployement, use {@link AuthPermission} on this login context.
245 public static Session
openDataAdminSession(Repository repository
, String workspaceName
) {
246 ClassLoader currentCl
= Thread
.currentThread().getContextClassLoader();
247 LoginContext loginContext
;
249 loginContext
= new LoginContext(CmsAuth
.LOGIN_CONTEXT_DATA_ADMIN
);
250 loginContext
.login();
251 } catch (LoginException e1
) {
252 throw new RuntimeException("Could not login as data admin", e1
);
254 Thread
.currentThread().setContextClassLoader(currentCl
);
256 return Subject
.doAs(loginContext
.getSubject(), new PrivilegedAction
<Session
>() {
259 public Session
run() {
261 return repository
.login(workspaceName
);
262 } catch (NoSuchWorkspaceException e
) {
263 throw new IllegalArgumentException("No workspace " + workspaceName
+ " available", e
);
264 } catch (RepositoryException e
) {
265 throw new RuntimeException("Cannot open data admin session", e
);
273 private CmsJcrUtils() {