2 * Copyright (C) 2007-2012 Argeo GmbH
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org
.argeo
.api
;
18 import java
.security
.PrivilegedAction
;
19 import java
.util
.HashMap
;
22 import javax
.jcr
.NoSuchWorkspaceException
;
23 import javax
.jcr
.Node
;
24 import javax
.jcr
.Repository
;
25 import javax
.jcr
.RepositoryException
;
26 import javax
.jcr
.RepositoryFactory
;
27 import javax
.jcr
.Session
;
28 import javax
.naming
.InvalidNameException
;
29 import javax
.naming
.ldap
.LdapName
;
30 import javax
.security
.auth
.AuthPermission
;
31 import javax
.security
.auth
.Subject
;
32 import javax
.security
.auth
.login
.LoginContext
;
33 import javax
.security
.auth
.login
.LoginException
;
35 /** Utilities related to Argeo model in JCR */
36 public class NodeUtils
{
38 * Wraps the call to the repository factory based on parameter
39 * {@link NodeConstants#CN} in order to simplify it and protect against future
42 public static Repository
getRepositoryByAlias(RepositoryFactory repositoryFactory
, String alias
) {
44 Map
<String
, String
> parameters
= new HashMap
<String
, String
>();
45 parameters
.put(NodeConstants
.CN
, alias
);
46 return repositoryFactory
.getRepository(parameters
);
47 } catch (RepositoryException e
) {
48 throw new RuntimeException("Unexpected exception when trying to retrieve repository with alias " + alias
,
54 * Wraps the call to the repository factory based on parameter
55 * {@link NodeConstants#LABELED_URI} in order to simplify it and protect against
58 public static Repository
getRepositoryByUri(RepositoryFactory repositoryFactory
, String uri
) {
59 return getRepositoryByUri(repositoryFactory
, uri
, null);
63 * Wraps the call to the repository factory based on parameter
64 * {@link NodeConstants#LABELED_URI} in order to simplify it and protect against
67 public static Repository
getRepositoryByUri(RepositoryFactory repositoryFactory
, String uri
, String alias
) {
69 Map
<String
, String
> parameters
= new HashMap
<String
, String
>();
70 parameters
.put(NodeConstants
.LABELED_URI
, uri
);
72 parameters
.put(NodeConstants
.CN
, alias
);
73 return repositoryFactory
.getRepository(parameters
);
74 } catch (RepositoryException e
) {
75 throw new RuntimeException("Unexpected exception when trying to retrieve repository with uri " + uri
, e
);
80 * Returns the home node of the user or null if none was found.
82 * @param session the session to use in order to perform the search, this can
83 * be a session with a different user ID than the one searched,
84 * typically when a system or admin session is used.
85 * @param username the username of the user
87 public static Node
getUserHome(Session session
, String username
) {
89 // QueryObjectModelFactory qomf = session.getWorkspace().getQueryManager().getQOMFactory();
90 // Selector sel = qomf.selector(NodeTypes.NODE_USER_HOME, "sel");
91 // DynamicOperand dop = qomf.propertyValue(sel.getSelectorName(), NodeNames.LDAP_UID);
92 // StaticOperand sop = qomf.literal(session.getValueFactory().createValue(username));
93 // Constraint constraint = qomf.comparison(dop, QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, sop);
94 // Query query = qomf.createQuery(sel, constraint, null, null);
95 // return querySingleNode(query);
96 // } catch (RepositoryException e) {
97 // throw new RuntimeException("Cannot find home for user " + username, e);
101 checkUserWorkspace(session
, username
);
102 String homePath
= getHomePath(username
);
103 if (session
.itemExists(homePath
))
104 return session
.getNode(homePath
);
106 homePath
= "/home/" + username
;
107 if (session
.itemExists(homePath
))
108 return session
.getNode(homePath
);
110 } catch (RepositoryException e
) {
111 throw new RuntimeException("Cannot find home for user " + username
, e
);
115 private static String
getHomePath(String username
) {
118 dn
= new LdapName(username
);
119 } catch (InvalidNameException e
) {
120 throw new IllegalArgumentException("Invalid name " + username
, e
);
122 String userId
= dn
.getRdn(dn
.size() - 1).getValue().toString();
126 private static void checkUserWorkspace(Session session
, String username
) {
127 String workspaceName
= session
.getWorkspace().getName();
128 if (!NodeConstants
.HOME_WORKSPACE
.equals(workspaceName
))
129 throw new IllegalArgumentException(workspaceName
+ " is not the home workspace for user " + username
);
133 * Returns the home node of the user or null if none was found.
135 * @param session the session to use in order to perform the search, this can
136 * be a session with a different user ID than the one searched,
137 * typically when a system or admin session is used.
138 * @param groupname the name of the group
140 public static Node
getGroupHome(Session session
, String groupname
) {
142 // QueryObjectModelFactory qomf = session.getWorkspace().getQueryManager().getQOMFactory();
143 // Selector sel = qomf.selector(NodeTypes.NODE_GROUP_HOME, "sel");
144 // DynamicOperand dop = qomf.propertyValue(sel.getSelectorName(), NodeNames.LDAP_CN);
145 // StaticOperand sop = qomf.literal(session.getValueFactory().createValue(cn));
146 // Constraint constraint = qomf.comparison(dop, QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, sop);
147 // Query query = qomf.createQuery(sel, constraint, null, null);
148 // return querySingleNode(query);
149 // } catch (RepositoryException e) {
150 // throw new RuntimeException("Cannot find home for group " + cn, e);
154 checkGroupWorkspace(session
, groupname
);
155 String homePath
= getGroupPath(groupname
);
156 if (session
.itemExists(homePath
))
157 return session
.getNode(homePath
);
159 homePath
= "/groups/" + groupname
;
160 if (session
.itemExists(homePath
))
161 return session
.getNode(homePath
);
163 } catch (RepositoryException e
) {
164 throw new RuntimeException("Cannot find home for group " + groupname
, e
);
169 private static String
getGroupPath(String groupname
) {
172 LdapName dn
= new LdapName(groupname
);
173 cn
= dn
.getRdn(dn
.size() - 1).getValue().toString();
174 } catch (InvalidNameException e
) {
180 private static void checkGroupWorkspace(Session session
, String groupname
) {
181 String workspaceName
= session
.getWorkspace().getName();
182 if (!NodeConstants
.SRV_WORKSPACE
.equals(workspaceName
))
183 throw new IllegalArgumentException(workspaceName
+ " is not the group workspace for group " + groupname
);
187 * Queries one single node.
189 * @return one single node or null if none was found
190 * @throws ArgeoJcrException if more than one node was found
192 // private static Node querySingleNode(Query query) {
193 // NodeIterator nodeIterator;
195 // QueryResult queryResult = query.execute();
196 // nodeIterator = queryResult.getNodes();
197 // } catch (RepositoryException e) {
198 // throw new RuntimeException("Cannot execute query " + query, e);
201 // if (nodeIterator.hasNext())
202 // node = nodeIterator.nextNode();
206 // if (nodeIterator.hasNext())
207 // throw new RuntimeException("Query returned more than one node.");
211 /** Returns the home node of the session user or null if none was found. */
212 public static Node
getUserHome(Session session
) {
213 String userID
= session
.getUserID();
214 return getUserHome(session
, userID
);
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
) throws RepositoryException
{
223 StringBuilder buf
= new StringBuilder(NodeConstants
.PATH_DATA
);
224 return buf
.append('/').append(cn
).append('/').append(node
.getSession().getWorkspace().getName())
225 .append(node
.getPath()).toString();
229 * Open a JCR session with full read/write rights on the data, as
230 * {@link NodeConstants#ROLE_USER_ADMIN}, using the
231 * {@link NodeConstants#LOGIN_CONTEXT_DATA_ADMIN} login context. For security
232 * hardened deployement, use {@link AuthPermission} on this login context.
234 public static Session
openDataAdminSession(Repository repository
, String workspaceName
) {
235 ClassLoader currentCl
= Thread
.currentThread().getContextClassLoader();
236 LoginContext loginContext
;
238 loginContext
= new LoginContext(NodeConstants
.LOGIN_CONTEXT_DATA_ADMIN
);
239 loginContext
.login();
240 } catch (LoginException e1
) {
241 throw new RuntimeException("Could not login as data admin", e1
);
243 Thread
.currentThread().setContextClassLoader(currentCl
);
245 return Subject
.doAs(loginContext
.getSubject(), new PrivilegedAction
<Session
>() {
248 public Session
run() {
250 return repository
.login(workspaceName
);
251 } catch (NoSuchWorkspaceException e
) {
252 throw new IllegalArgumentException("No workspace " + workspaceName
+ " available", e
);
253 } catch (RepositoryException e
) {
254 throw new RuntimeException("Cannot open data admin session", e
);
262 private NodeUtils() {