View Javadoc
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.jcr;
17  
18  import java.security.Principal;
19  import java.util.ArrayList;
20  import java.util.HashMap;
21  import java.util.List;
22  import java.util.Map;
23  
24  import javax.jcr.Repository;
25  import javax.jcr.RepositoryException;
26  import javax.jcr.Session;
27  import javax.jcr.security.AccessControlManager;
28  import javax.jcr.security.Privilege;
29  import javax.naming.InvalidNameException;
30  import javax.naming.ldap.LdapName;
31  
32  /** Apply authorizations to a JCR repository. */
33  public class JcrAuthorizations implements Runnable {
34  	// private final static Log log =
35  	// LogFactory.getLog(JcrAuthorizations.class);
36  
37  	private Repository repository;
38  	private String workspace = null;
39  
40  	private String securityWorkspace = "security";
41  
42  	/**
43  	 * key := privilege1,privilege2/path/to/node<br/>
44  	 * value := group1,group2,user1
45  	 */
46  	private Map<String, String> principalPrivileges = new HashMap<String, String>();
47  
48  	public void run() {
49  		String currentWorkspace = workspace;
50  		Session session = null;
51  		try {
52  			if (workspace != null && workspace.equals("*")) {
53  				session = repository.login();
54  				String[] workspaces = session.getWorkspace().getAccessibleWorkspaceNames();
55  				JcrUtils.logoutQuietly(session);
56  				for (String wksp : workspaces) {
57  					currentWorkspace = wksp;
58  					if (currentWorkspace.equals(securityWorkspace))
59  						continue;
60  					session = repository.login(currentWorkspace);
61  					initAuthorizations(session);
62  					JcrUtils.logoutQuietly(session);
63  				}
64  			} else {
65  				session = repository.login(workspace);
66  				initAuthorizations(session);
67  			}
68  		} catch (Exception e) {
69  			JcrUtils.discardQuietly(session);
70  			throw new ArgeoJcrException(
71  					"Cannot set authorizations " + principalPrivileges + " on workspace " + currentWorkspace, e);
72  		} finally {
73  			JcrUtils.logoutQuietly(session);
74  		}
75  	}
76  
77  	protected void processWorkspace(String workspace) {
78  		Session session = null;
79  		try {
80  			session = repository.login(workspace);
81  			initAuthorizations(session);
82  		} catch (Exception e) {
83  			JcrUtils.discardQuietly(session);
84  			throw new ArgeoJcrException(
85  					"Cannot set authorizations " + principalPrivileges + " on repository " + repository, e);
86  		} finally {
87  			JcrUtils.logoutQuietly(session);
88  		}
89  	}
90  
91  	/** @deprecated call {@link #run()} instead. */
92  	@Deprecated
93  	public void init() {
94  		run();
95  	}
96  
97  	protected void initAuthorizations(Session session) throws RepositoryException {
98  		AccessControlManager acm = session.getAccessControlManager();
99  
100 		for (String privileges : principalPrivileges.keySet()) {
101 			String path = null;
102 			int slashIndex = privileges.indexOf('/');
103 			if (slashIndex == 0) {
104 				throw new ArgeoJcrException("Privilege " + privileges + " badly formatted it starts with /");
105 			} else if (slashIndex > 0) {
106 				path = privileges.substring(slashIndex);
107 				privileges = privileges.substring(0, slashIndex);
108 			}
109 
110 			if (path == null)
111 				path = "/";
112 
113 			List<Privilege> privs = new ArrayList<Privilege>();
114 			for (String priv : privileges.split(",")) {
115 				privs.add(acm.privilegeFromName(priv));
116 			}
117 
118 			String principalNames = principalPrivileges.get(privileges);
119 			try {
120 				new LdapName(principalNames);
121 				// TODO differentiate groups and users ?
122 				Principal principal = getOrCreatePrincipal(session, principalNames);
123 				JcrUtils.addPrivileges(session, path, principal, privs);
124 			} catch (InvalidNameException e) {
125 				for (String principalName : principalNames.split(",")) {
126 					Principal principal = getOrCreatePrincipal(session, principalName);
127 					JcrUtils.addPrivileges(session, path, principal, privs);
128 					// if (log.isDebugEnabled()) {
129 					// StringBuffer privBuf = new StringBuffer();
130 					// for (Privilege priv : privs)
131 					// privBuf.append(priv.getName());
132 					// log.debug("Added privileges " + privBuf + " to "
133 					// + principal.getName() + " on " + path + " in '"
134 					// + session.getWorkspace().getName() + "'");
135 					// }
136 				}
137 			}
138 		}
139 
140 		// if (log.isDebugEnabled())
141 		// log.debug("JCR authorizations applied on '"
142 		// + session.getWorkspace().getName() + "'");
143 	}
144 
145 	/**
146 	 * Returns a {@link SimplePrincipal}, does not check whether it exists since
147 	 * such capabilities is not provided by the standard JCR API. Can be
148 	 * overridden to provide smarter handling
149 	 */
150 	protected Principal getOrCreatePrincipal(Session session, String principalName) throws RepositoryException {
151 		return new SimplePrincipal(principalName);
152 	}
153 
154 	// public static void addPrivileges(Session session, Principal principal,
155 	// String path, List<Privilege> privs) throws RepositoryException {
156 	// AccessControlManager acm = session.getAccessControlManager();
157 	// // search for an access control list
158 	// AccessControlList acl = null;
159 	// AccessControlPolicyIterator policyIterator = acm
160 	// .getApplicablePolicies(path);
161 	// if (policyIterator.hasNext()) {
162 	// while (policyIterator.hasNext()) {
163 	// AccessControlPolicy acp = policyIterator
164 	// .nextAccessControlPolicy();
165 	// if (acp instanceof AccessControlList)
166 	// acl = ((AccessControlList) acp);
167 	// }
168 	// } else {
169 	// AccessControlPolicy[] existingPolicies = acm.getPolicies(path);
170 	// for (AccessControlPolicy acp : existingPolicies) {
171 	// if (acp instanceof AccessControlList)
172 	// acl = ((AccessControlList) acp);
173 	// }
174 	// }
175 	//
176 	// if (acl != null) {
177 	// acl.addAccessControlEntry(principal,
178 	// privs.toArray(new Privilege[privs.size()]));
179 	// acm.setPolicy(path, acl);
180 	// session.save();
181 	// if (log.isDebugEnabled()) {
182 	// StringBuffer buf = new StringBuffer("");
183 	// for (int i = 0; i < privs.size(); i++) {
184 	// if (i != 0)
185 	// buf.append(',');
186 	// buf.append(privs.get(i).getName());
187 	// }
188 	// log.debug("Added privilege(s) '" + buf + "' to '"
189 	// + principal.getName() + "' on " + path
190 	// + " from workspace '"
191 	// + session.getWorkspace().getName() + "'");
192 	// }
193 	// } else {
194 	// throw new ArgeoJcrException("Don't know how to apply privileges "
195 	// + privs + " to " + principal + " on " + path
196 	// + " from workspace '" + session.getWorkspace().getName()
197 	// + "'");
198 	// }
199 	// }
200 
201 	@Deprecated
202 	public void setGroupPrivileges(Map<String, String> groupPrivileges) {
203 		this.principalPrivileges = groupPrivileges;
204 	}
205 
206 	public void setPrincipalPrivileges(Map<String, String> principalPrivileges) {
207 		this.principalPrivileges = principalPrivileges;
208 	}
209 
210 	public void setRepository(Repository repository) {
211 		this.repository = repository;
212 	}
213 
214 	public void setWorkspace(String workspace) {
215 		this.workspace = workspace;
216 	}
217 
218 	public void setSecurityWorkspace(String securityWorkspace) {
219 		this.securityWorkspace = securityWorkspace;
220 	}
221 
222 }