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
.node
;
18 import java
.security
.PrivilegedAction
;
19 import java
.util
.HashMap
;
22 import javax
.jcr
.NoSuchWorkspaceException
;
23 import javax
.jcr
.Node
;
24 import javax
.jcr
.NodeIterator
;
25 import javax
.jcr
.Repository
;
26 import javax
.jcr
.RepositoryException
;
27 import javax
.jcr
.RepositoryFactory
;
28 import javax
.jcr
.Session
;
29 import javax
.jcr
.query
.Query
;
30 import javax
.jcr
.query
.QueryResult
;
31 import javax
.jcr
.query
.qom
.Constraint
;
32 import javax
.jcr
.query
.qom
.DynamicOperand
;
33 import javax
.jcr
.query
.qom
.QueryObjectModelFactory
;
34 import javax
.jcr
.query
.qom
.Selector
;
35 import javax
.jcr
.query
.qom
.StaticOperand
;
36 import javax
.security
.auth
.AuthPermission
;
37 import javax
.security
.auth
.Subject
;
38 import javax
.security
.auth
.login
.LoginContext
;
39 import javax
.security
.auth
.login
.LoginException
;
41 /** Utilities related to Argeo model in JCR */
42 public class NodeUtils
{
44 * Wraps the call to the repository factory based on parameter
45 * {@link NodeConstants#CN} in order to simplify it and protect against future
48 public static Repository
getRepositoryByAlias(RepositoryFactory repositoryFactory
, String alias
) {
50 Map
<String
, String
> parameters
= new HashMap
<String
, String
>();
51 parameters
.put(NodeConstants
.CN
, alias
);
52 return repositoryFactory
.getRepository(parameters
);
53 } catch (RepositoryException e
) {
54 throw new RuntimeException("Unexpected exception when trying to retrieve repository with alias " + alias
,
60 * Wraps the call to the repository factory based on parameter
61 * {@link NodeConstants#LABELED_URI} in order to simplify it and protect against
64 public static Repository
getRepositoryByUri(RepositoryFactory repositoryFactory
, String uri
) {
65 return getRepositoryByUri(repositoryFactory
, uri
, null);
69 * Wraps the call to the repository factory based on parameter
70 * {@link NodeConstants#LABELED_URI} in order to simplify it and protect against
73 public static Repository
getRepositoryByUri(RepositoryFactory repositoryFactory
, String uri
, String alias
) {
75 Map
<String
, String
> parameters
= new HashMap
<String
, String
>();
76 parameters
.put(NodeConstants
.LABELED_URI
, uri
);
78 parameters
.put(NodeConstants
.CN
, alias
);
79 return repositoryFactory
.getRepository(parameters
);
80 } catch (RepositoryException e
) {
81 throw new RuntimeException("Unexpected exception when trying to retrieve repository with uri " + uri
, e
);
86 * Returns the home node of the user or null if none was found.
88 * @param session the session to use in order to perform the search, this can
89 * be a session with a different user ID than the one searched,
90 * typically when a system or admin session is used.
91 * @param username the username of the user
93 public static Node
getUserHome(Session session
, String username
) {
95 QueryObjectModelFactory qomf
= session
.getWorkspace().getQueryManager().getQOMFactory();
96 Selector sel
= qomf
.selector(NodeTypes
.NODE_USER_HOME
, "sel");
97 DynamicOperand dop
= qomf
.propertyValue(sel
.getSelectorName(), NodeNames
.LDAP_UID
);
98 StaticOperand sop
= qomf
.literal(session
.getValueFactory().createValue(username
));
99 Constraint constraint
= qomf
.comparison(dop
, QueryObjectModelFactory
.JCR_OPERATOR_EQUAL_TO
, sop
);
100 Query query
= qomf
.createQuery(sel
, constraint
, null, null);
101 return querySingleNode(query
);
102 } catch (RepositoryException e
) {
103 throw new RuntimeException("Cannot find home for user " + username
, e
);
108 * Returns the home node of the user or null if none was found.
110 * @param session the session to use in order to perform the search, this can be
111 * a session with a different user ID than the one searched,
112 * typically when a system or admin session is used.
113 * @param cn the name of the group
115 public static Node
getGroupHome(Session session
, String cn
) {
117 QueryObjectModelFactory qomf
= session
.getWorkspace().getQueryManager().getQOMFactory();
118 Selector sel
= qomf
.selector(NodeTypes
.NODE_GROUP_HOME
, "sel");
119 DynamicOperand dop
= qomf
.propertyValue(sel
.getSelectorName(), NodeNames
.LDAP_CN
);
120 StaticOperand sop
= qomf
.literal(session
.getValueFactory().createValue(cn
));
121 Constraint constraint
= qomf
.comparison(dop
, QueryObjectModelFactory
.JCR_OPERATOR_EQUAL_TO
, sop
);
122 Query query
= qomf
.createQuery(sel
, constraint
, null, null);
123 return querySingleNode(query
);
124 } catch (RepositoryException e
) {
125 throw new RuntimeException("Cannot find home for user " + cn
, e
);
130 * Queries one single node.
132 * @return one single node or null if none was found
133 * @throws ArgeoJcrException if more than one node was found
135 private static Node
querySingleNode(Query query
) {
136 NodeIterator nodeIterator
;
138 QueryResult queryResult
= query
.execute();
139 nodeIterator
= queryResult
.getNodes();
140 } catch (RepositoryException e
) {
141 throw new RuntimeException("Cannot execute query " + query
, e
);
144 if (nodeIterator
.hasNext())
145 node
= nodeIterator
.nextNode();
149 if (nodeIterator
.hasNext())
150 throw new RuntimeException("Query returned more than one node.");
154 /** Returns the home node of the session user or null if none was found. */
155 public static Node
getUserHome(Session session
) {
156 String userID
= session
.getUserID();
157 return getUserHome(session
, userID
);
161 * Translate the path to this node into a path containing the name of the
162 * repository and the name of the workspace.
164 public static String
getDataPath(String cn
, Node node
) throws RepositoryException
{
166 StringBuilder buf
= new StringBuilder(NodeConstants
.PATH_DATA
);
167 return buf
.append('/').append(cn
).append('/').append(node
.getSession().getWorkspace().getName())
168 .append(node
.getPath()).toString();
172 * Open a JCR session with full read/write rights on the data, as
173 * {@link NodeConstants#ROLE_USER_ADMIN}, using the
174 * {@link NodeConstants#LOGIN_CONTEXT_DATA_ADMIN} login context. For security
175 * hardened deployement, use {@link AuthPermission} on this login context.
177 public static Session
openDataAdminSession(Repository repository
, String workspaceName
) {
178 ClassLoader currentCl
= Thread
.currentThread().getContextClassLoader();
179 LoginContext loginContext
;
181 loginContext
= new LoginContext(NodeConstants
.LOGIN_CONTEXT_DATA_ADMIN
);
182 loginContext
.login();
183 } catch (LoginException e1
) {
184 throw new RuntimeException("Could not login as data admin", e1
);
186 Thread
.currentThread().setContextClassLoader(currentCl
);
188 return Subject
.doAs(loginContext
.getSubject(), new PrivilegedAction
<Session
>() {
191 public Session
run() {
193 return repository
.login(workspaceName
);
194 } catch (NoSuchWorkspaceException e
) {
195 throw new IllegalArgumentException("No workspace " + workspaceName
+ " available", e
);
196 } catch (RepositoryException e
) {
197 throw new RuntimeException("Cannot open data admin session", e
);
205 private NodeUtils() {