]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.node.api/src/org/argeo/node/NodeUtils.java
Make ident login plugin more robust.
[lgpl/argeo-commons.git] / org.argeo.node.api / src / org / argeo / node / NodeUtils.java
1 /*
2 * Copyright (C) 2007-2012 Argeo GmbH
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16 package org.argeo.node;
17
18 import java.security.PrivilegedAction;
19 import java.util.HashMap;
20 import java.util.Map;
21
22 import javax.jcr.Node;
23 import javax.jcr.NodeIterator;
24 import javax.jcr.Repository;
25 import javax.jcr.RepositoryException;
26 import javax.jcr.RepositoryFactory;
27 import javax.jcr.Session;
28 import javax.jcr.query.Query;
29 import javax.jcr.query.QueryResult;
30 import javax.jcr.query.qom.Constraint;
31 import javax.jcr.query.qom.DynamicOperand;
32 import javax.jcr.query.qom.QueryObjectModelFactory;
33 import javax.jcr.query.qom.Selector;
34 import javax.jcr.query.qom.StaticOperand;
35 import javax.security.auth.AuthPermission;
36 import javax.security.auth.Subject;
37 import javax.security.auth.login.LoginContext;
38 import javax.security.auth.login.LoginException;
39
40 /** Utilities related to Argeo model in JCR */
41 public class NodeUtils {
42 /**
43 * Wraps the call to the repository factory based on parameter
44 * {@link NodeConstants#CN} in order to simplify it and protect against future
45 * API changes.
46 */
47 public static Repository getRepositoryByAlias(RepositoryFactory repositoryFactory, String alias) {
48 try {
49 Map<String, String> parameters = new HashMap<String, String>();
50 parameters.put(NodeConstants.CN, alias);
51 return repositoryFactory.getRepository(parameters);
52 } catch (RepositoryException e) {
53 throw new RuntimeException("Unexpected exception when trying to retrieve repository with alias " + alias,
54 e);
55 }
56 }
57
58 /**
59 * Wraps the call to the repository factory based on parameter
60 * {@link NodeConstants#LABELED_URI} in order to simplify it and protect against
61 * future API changes.
62 */
63 public static Repository getRepositoryByUri(RepositoryFactory repositoryFactory, String uri) {
64 return getRepositoryByUri(repositoryFactory, uri, null);
65 }
66
67 /**
68 * Wraps the call to the repository factory based on parameter
69 * {@link NodeConstants#LABELED_URI} in order to simplify it and protect against
70 * future API changes.
71 */
72 public static Repository getRepositoryByUri(RepositoryFactory repositoryFactory, String uri, String alias) {
73 try {
74 Map<String, String> parameters = new HashMap<String, String>();
75 parameters.put(NodeConstants.LABELED_URI, uri);
76 if (alias != null)
77 parameters.put(NodeConstants.CN, alias);
78 return repositoryFactory.getRepository(parameters);
79 } catch (RepositoryException e) {
80 throw new RuntimeException("Unexpected exception when trying to retrieve repository with uri " + uri, e);
81 }
82 }
83
84 /**
85 * Returns the home node of the user or null if none was found.
86 *
87 * @param session the session to use in order to perform the search, this can
88 * be a session with a different user ID than the one searched,
89 * typically when a system or admin session is used.
90 * @param username the username of the user
91 */
92 public static Node getUserHome(Session session, String username) {
93 try {
94 QueryObjectModelFactory qomf = session.getWorkspace().getQueryManager().getQOMFactory();
95 Selector sel = qomf.selector(NodeTypes.NODE_USER_HOME, "sel");
96 DynamicOperand dop = qomf.propertyValue(sel.getSelectorName(), NodeNames.LDAP_UID);
97 StaticOperand sop = qomf.literal(session.getValueFactory().createValue(username));
98 Constraint constraint = qomf.comparison(dop, QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, sop);
99 Query query = qomf.createQuery(sel, constraint, null, null);
100 return querySingleNode(query);
101 } catch (RepositoryException e) {
102 throw new RuntimeException("Cannot find home for user " + username, e);
103 }
104 }
105
106 /**
107 * Returns the home node of the user or null if none was found.
108 *
109 * @param session the session to use in order to perform the search, this can be
110 * a session with a different user ID than the one searched,
111 * typically when a system or admin session is used.
112 * @param cn the name of the group
113 */
114 public static Node getGroupHome(Session session, String cn) {
115 try {
116 QueryObjectModelFactory qomf = session.getWorkspace().getQueryManager().getQOMFactory();
117 Selector sel = qomf.selector(NodeTypes.NODE_GROUP_HOME, "sel");
118 DynamicOperand dop = qomf.propertyValue(sel.getSelectorName(), NodeNames.LDAP_CN);
119 StaticOperand sop = qomf.literal(session.getValueFactory().createValue(cn));
120 Constraint constraint = qomf.comparison(dop, QueryObjectModelFactory.JCR_OPERATOR_EQUAL_TO, sop);
121 Query query = qomf.createQuery(sel, constraint, null, null);
122 return querySingleNode(query);
123 } catch (RepositoryException e) {
124 throw new RuntimeException("Cannot find home for user " + cn, e);
125 }
126 }
127
128 /**
129 * Queries one single node.
130 *
131 * @return one single node or null if none was found
132 * @throws ArgeoJcrException if more than one node was found
133 */
134 private static Node querySingleNode(Query query) {
135 NodeIterator nodeIterator;
136 try {
137 QueryResult queryResult = query.execute();
138 nodeIterator = queryResult.getNodes();
139 } catch (RepositoryException e) {
140 throw new RuntimeException("Cannot execute query " + query, e);
141 }
142 Node node;
143 if (nodeIterator.hasNext())
144 node = nodeIterator.nextNode();
145 else
146 return null;
147
148 if (nodeIterator.hasNext())
149 throw new RuntimeException("Query returned more than one node.");
150 return node;
151 }
152
153 /** Returns the home node of the session user or null if none was found. */
154 public static Node getUserHome(Session session) {
155 String userID = session.getUserID();
156 return getUserHome(session, userID);
157 }
158
159 /**
160 * Translate the path to this node into a path containing the name of the
161 * repository and the name of the workspace.
162 */
163 public static String getDataPath(String cn, Node node) throws RepositoryException {
164 assert node != null;
165 StringBuilder buf = new StringBuilder(NodeConstants.PATH_DATA);
166 return buf.append('/').append(cn).append('/').append(node.getSession().getWorkspace().getName())
167 .append(node.getPath()).toString();
168 }
169
170 /**
171 * Open a JCR session with full read/write rights on the data, as
172 * {@link NodeConstants#ROLE_USER_ADMIN}, using the
173 * {@link NodeConstants#LOGIN_CONTEXT_DATA_ADMIN} login context. For security
174 * hardened deployement, use {@link AuthPermission} on this login context.
175 */
176 public static Session openDataAdminSession(Repository repository, String workspaceName) {
177 ClassLoader currentCl = Thread.currentThread().getContextClassLoader();
178 LoginContext loginContext;
179 try {
180 loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_DATA_ADMIN);
181 loginContext.login();
182 } catch (LoginException e1) {
183 throw new RuntimeException("Could not login as data admin", e1);
184 } finally {
185 Thread.currentThread().setContextClassLoader(currentCl);
186 }
187 return Subject.doAs(loginContext.getSubject(), new PrivilegedAction<Session>() {
188
189 @Override
190 public Session run() {
191 try {
192 return repository.login(workspaceName);
193 } catch (RepositoryException e) {
194 throw new RuntimeException("Cannot open data admin session", e);
195 }
196 }
197
198 });
199 }
200
201 /** Singleton. */
202 private NodeUtils() {
203 }
204
205 }