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