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
;
23 import org
.argeo
.jcr
.JcrUtils
;
25 /** Utilities related to Argeo model in JCR */
26 public class CmsJcrUtils
{
28 * Wraps the call to the repository factory based on parameter
29 * {@link CmsConstants#CN} in order to simplify it and protect against future
32 public static Repository
getRepositoryByAlias(RepositoryFactory repositoryFactory
, String alias
) {
34 Map
<String
, String
> parameters
= new HashMap
<String
, String
>();
35 parameters
.put(CmsConstants
.CN
, alias
);
36 return repositoryFactory
.getRepository(parameters
);
37 } catch (RepositoryException e
) {
38 throw new RuntimeException("Unexpected exception when trying to retrieve repository with alias " + alias
,
44 * Wraps the call to the repository factory based on parameter
45 * {@link CmsConstants#LABELED_URI} in order to simplify it and protect against
48 public static Repository
getRepositoryByUri(RepositoryFactory repositoryFactory
, String uri
) {
49 return getRepositoryByUri(repositoryFactory
, uri
, null);
53 * Wraps the call to the repository factory based on parameter
54 * {@link CmsConstants#LABELED_URI} in order to simplify it and protect against
57 public static Repository
getRepositoryByUri(RepositoryFactory repositoryFactory
, String uri
, String alias
) {
59 Map
<String
, String
> parameters
= new HashMap
<String
, String
>();
60 parameters
.put(CmsConstants
.LABELED_URI
, uri
);
62 parameters
.put(CmsConstants
.CN
, alias
);
63 return repositoryFactory
.getRepository(parameters
);
64 } catch (RepositoryException e
) {
65 throw new RuntimeException("Unexpected exception when trying to retrieve repository with uri " + uri
, e
);
70 * Returns the home node of the user or null if none was found.
72 * @param session the session to use in order to perform the search, this can
73 * be a session with a different user ID than the one searched,
74 * typically when a system or admin session is used.
75 * @param username the username of the user
77 public static Node
getUserHome(Session session
, String username
) {
79 // QueryObjectModelFactory qomf = session.getWorkspace().getQueryManager().getQOMFactory();
80 // Selector sel = qomf.selector(NodeTypes.NODE_USER_HOME, "sel");
81 // DynamicOperand dop = qomf.propertyValue(sel.getSelectorName(), NodeNames.LDAP_UID);
82 // StaticOperand sop = qomf.literal(session.getValueFactory().createValue(username));
83 // Constraint constraint = qomf.comparison(dop, QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, sop);
84 // Query query = qomf.createQuery(sel, constraint, null, null);
85 // return querySingleNode(query);
86 // } catch (RepositoryException e) {
87 // throw new RuntimeException("Cannot find home for user " + username, e);
91 checkUserWorkspace(session
, username
);
92 String homePath
= getHomePath(username
);
93 if (session
.itemExists(homePath
))
94 return session
.getNode(homePath
);
96 homePath
= "/home/" + username
;
97 if (session
.itemExists(homePath
))
98 return session
.getNode(homePath
);
100 } catch (RepositoryException e
) {
101 throw new RuntimeException("Cannot find home for user " + username
, e
);
105 private static String
getHomePath(String username
) {
108 dn
= new LdapName(username
);
109 } catch (InvalidNameException e
) {
110 throw new IllegalArgumentException("Invalid name " + username
, e
);
112 String userId
= dn
.getRdn(dn
.size() - 1).getValue().toString();
116 private static void checkUserWorkspace(Session session
, String username
) {
117 String workspaceName
= session
.getWorkspace().getName();
118 if (!CmsConstants
.HOME_WORKSPACE
.equals(workspaceName
))
119 throw new IllegalArgumentException(workspaceName
+ " is not the home workspace for user " + username
);
123 * Returns the home node of the user or null if none was found.
125 * @param session the session to use in order to perform the search, this can
126 * be a session with a different user ID than the one searched,
127 * typically when a system or admin session is used.
128 * @param groupname the name of the group
130 public static Node
getGroupHome(Session session
, String groupname
) {
132 // QueryObjectModelFactory qomf = session.getWorkspace().getQueryManager().getQOMFactory();
133 // Selector sel = qomf.selector(NodeTypes.NODE_GROUP_HOME, "sel");
134 // DynamicOperand dop = qomf.propertyValue(sel.getSelectorName(), NodeNames.LDAP_CN);
135 // StaticOperand sop = qomf.literal(session.getValueFactory().createValue(cn));
136 // Constraint constraint = qomf.comparison(dop, QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, sop);
137 // Query query = qomf.createQuery(sel, constraint, null, null);
138 // return querySingleNode(query);
139 // } catch (RepositoryException e) {
140 // throw new RuntimeException("Cannot find home for group " + cn, e);
144 checkGroupWorkspace(session
, groupname
);
145 String homePath
= getGroupPath(groupname
);
146 if (session
.itemExists(homePath
))
147 return session
.getNode(homePath
);
149 homePath
= "/groups/" + groupname
;
150 if (session
.itemExists(homePath
))
151 return session
.getNode(homePath
);
153 } catch (RepositoryException e
) {
154 throw new RuntimeException("Cannot find home for group " + groupname
, e
);
159 private static String
getGroupPath(String groupname
) {
162 LdapName dn
= new LdapName(groupname
);
163 cn
= dn
.getRdn(dn
.size() - 1).getValue().toString();
164 } catch (InvalidNameException e
) {
170 private static void checkGroupWorkspace(Session session
, String groupname
) {
171 String workspaceName
= session
.getWorkspace().getName();
172 if (!CmsConstants
.SRV_WORKSPACE
.equals(workspaceName
))
173 throw new IllegalArgumentException(workspaceName
+ " is not the group workspace for group " + groupname
);
177 * Queries one single node.
179 * @return one single node or null if none was found
180 * @throws ArgeoJcrException if more than one node was found
182 // private static Node querySingleNode(Query query) {
183 // NodeIterator nodeIterator;
185 // QueryResult queryResult = query.execute();
186 // nodeIterator = queryResult.getNodes();
187 // } catch (RepositoryException e) {
188 // throw new RuntimeException("Cannot execute query " + query, e);
191 // if (nodeIterator.hasNext())
192 // node = nodeIterator.nextNode();
196 // if (nodeIterator.hasNext())
197 // throw new RuntimeException("Query returned more than one node.");
201 /** Returns the home node of the session user or null if none was found. */
202 public static Node
getUserHome(Session session
) {
203 String userID
= session
.getUserID();
204 return getUserHome(session
, userID
);
207 /** Whether this node is the home of the user of the underlying session. */
208 public static boolean isUserHome(Node node
) {
210 String userID
= node
.getSession().getUserID();
211 return node
.hasProperty(Property
.JCR_ID
) && node
.getProperty(Property
.JCR_ID
).getString().equals(userID
);
212 } catch (RepositoryException e
) {
213 throw new IllegalStateException(e
);
218 * Translate the path to this node into a path containing the name of the
219 * repository and the name of the workspace.
221 public static String
getDataPath(String cn
, Node node
) {
223 StringBuilder buf
= new StringBuilder(CmsConstants
.PATH_DATA
);
225 return buf
.append('/').append(cn
).append('/').append(node
.getSession().getWorkspace().getName())
226 .append(node
.getPath()).toString();
227 } catch (RepositoryException e
) {
228 throw new IllegalStateException("Cannot get data path for " + node
+ " in repository " + cn
, e
);
233 * Translate the path to this node into a path containing the name of the
234 * repository and the name of the workspace.
236 public static String
getDataPath(Node node
) {
237 return getDataPath(CmsConstants
.NODE
, node
);
241 * Open a JCR session with full read/write rights on the data, as
242 * {@link CmsConstants#ROLE_USER_ADMIN}, using the
243 * {@link CmsAuth#LOGIN_CONTEXT_DATA_ADMIN} login context. For security hardened
244 * deployement, use {@link AuthPermission} on this login context.
246 public static Session
openDataAdminSession(Repository repository
, String workspaceName
) {
247 LoginContext loginContext
;
249 loginContext
= CmsAuth
.DATA_ADMIN
.newLoginContext();
250 loginContext
.login();
251 } catch (LoginException e1
) {
252 throw new RuntimeException("Could not login as data admin", e1
);
256 ClassLoader currentCl
= Thread
.currentThread().getContextClassLoader();
258 Thread
.currentThread().setContextClassLoader(CmsJcrUtils
.class.getClassLoader());
259 return Subject
.doAs(loginContext
.getSubject(), new PrivilegedAction
<Session
>() {
262 public Session
run() {
264 return JcrUtils
.loginOrCreateWorkspace(repository
, workspaceName
);
265 } catch (NoSuchWorkspaceException e
) {// should not happen
266 throw new IllegalArgumentException("No workspace " + workspaceName
+ " available", e
);
267 } catch (RepositoryException e
) {
268 throw new RuntimeException("Cannot open data admin session", e
);
274 Thread
.currentThread().setContextClassLoader(currentCl
);
279 private CmsJcrUtils() {