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
.NodeConstants
;
23 /** Utilities related to Argeo model in JCR */
24 public class CmsJcrUtils
{
26 * Wraps the call to the repository factory based on parameter
27 * {@link NodeConstants#CN} in order to simplify it and protect against future
30 public static Repository
getRepositoryByAlias(RepositoryFactory repositoryFactory
, String alias
) {
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
,
42 * Wraps the call to the repository factory based on parameter
43 * {@link NodeConstants#LABELED_URI} in order to simplify it and protect against
46 public static Repository
getRepositoryByUri(RepositoryFactory repositoryFactory
, String uri
) {
47 return getRepositoryByUri(repositoryFactory
, uri
, null);
51 * Wraps the call to the repository factory based on parameter
52 * {@link NodeConstants#LABELED_URI} in order to simplify it and protect against
55 public static Repository
getRepositoryByUri(RepositoryFactory repositoryFactory
, String uri
, String alias
) {
57 Map
<String
, String
> parameters
= new HashMap
<String
, String
>();
58 parameters
.put(NodeConstants
.LABELED_URI
, uri
);
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
);
68 * Returns the home node of the user or null if none was found.
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
75 public static Node
getUserHome(Session session
, String username
) {
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);
89 checkUserWorkspace(session
, username
);
90 String homePath
= getHomePath(username
);
91 if (session
.itemExists(homePath
))
92 return session
.getNode(homePath
);
94 homePath
= "/home/" + username
;
95 if (session
.itemExists(homePath
))
96 return session
.getNode(homePath
);
98 } catch (RepositoryException e
) {
99 throw new RuntimeException("Cannot find home for user " + username
, e
);
103 private static String
getHomePath(String username
) {
106 dn
= new LdapName(username
);
107 } catch (InvalidNameException e
) {
108 throw new IllegalArgumentException("Invalid name " + username
, e
);
110 String userId
= dn
.getRdn(dn
.size() - 1).getValue().toString();
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
);
121 * Returns the home node of the user or null if none was found.
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
128 public static Node
getGroupHome(Session session
, String groupname
) {
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);
142 checkGroupWorkspace(session
, groupname
);
143 String homePath
= getGroupPath(groupname
);
144 if (session
.itemExists(homePath
))
145 return session
.getNode(homePath
);
147 homePath
= "/groups/" + groupname
;
148 if (session
.itemExists(homePath
))
149 return session
.getNode(homePath
);
151 } catch (RepositoryException e
) {
152 throw new RuntimeException("Cannot find home for group " + groupname
, e
);
157 private static String
getGroupPath(String groupname
) {
160 LdapName dn
= new LdapName(groupname
);
161 cn
= dn
.getRdn(dn
.size() - 1).getValue().toString();
162 } catch (InvalidNameException e
) {
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
);
175 * Queries one single node.
177 * @return one single node or null if none was found
178 * @throws ArgeoJcrException if more than one node was found
180 // private static Node querySingleNode(Query query) {
181 // NodeIterator nodeIterator;
183 // QueryResult queryResult = query.execute();
184 // nodeIterator = queryResult.getNodes();
185 // } catch (RepositoryException e) {
186 // throw new RuntimeException("Cannot execute query " + query, e);
189 // if (nodeIterator.hasNext())
190 // node = nodeIterator.nextNode();
194 // if (nodeIterator.hasNext())
195 // throw new RuntimeException("Query returned more than one node.");
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
);
205 /** Whether this node is the home of the user of the underlying session. */
206 public static boolean isUserHome(Node node
) {
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
);
216 * Translate the path to this node into a path containing the name of the
217 * repository and the name of the workspace.
219 public static String
getDataPath(String cn
, Node node
) {
221 StringBuilder buf
= new StringBuilder(NodeConstants
.PATH_DATA
);
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
);
231 * Translate the path to this node into a path containing the name of the
232 * repository and the name of the workspace.
234 public static String
getDataPath(Node node
) {
235 return getDataPath(NodeConstants
.NODE
, node
);
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.
244 public static Session
openDataAdminSession(Repository repository
, String workspaceName
) {
245 ClassLoader currentCl
= Thread
.currentThread().getContextClassLoader();
246 LoginContext loginContext
;
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
);
253 Thread
.currentThread().setContextClassLoader(currentCl
);
255 return Subject
.doAs(loginContext
.getSubject(), new PrivilegedAction
<Session
>() {
258 public Session
run() {
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
);
272 private CmsJcrUtils() {