]> git.argeo.org Git - lgpl/argeo-commons.git/blob - jcr/org.argeo.cms.jcr/src/org/argeo/maintenance/AbstractMaintenanceService.java
Make open admin session more robust.
[lgpl/argeo-commons.git] / jcr / org.argeo.cms.jcr / src / org / argeo / maintenance / AbstractMaintenanceService.java
1 package org.argeo.maintenance;
2
3 import java.io.IOException;
4 import java.util.EnumSet;
5 import java.util.HashSet;
6 import java.util.Set;
7
8 import javax.jcr.NoSuchWorkspaceException;
9 import javax.jcr.Repository;
10 import javax.jcr.RepositoryException;
11 import javax.jcr.Session;
12
13 import org.argeo.api.cms.CmsLog;
14 import org.argeo.cms.jcr.CmsJcrUtils;
15 import org.argeo.jcr.Jcr;
16 import org.argeo.jcr.JcrUtils;
17 import org.argeo.osgi.transaction.WorkTransaction;
18 import org.argeo.util.naming.Distinguished;
19 import org.osgi.service.useradmin.Group;
20 import org.osgi.service.useradmin.Role;
21 import org.osgi.service.useradmin.UserAdmin;
22
23 /** Make sure roles and access rights are properly configured. */
24 public abstract class AbstractMaintenanceService {
25 private final static CmsLog log = CmsLog.getLog(AbstractMaintenanceService.class);
26
27 private Repository repository;
28 // private UserAdminService userAdminService;
29 private UserAdmin userAdmin;
30 private WorkTransaction userTransaction;
31
32 public void init() {
33 makeSureRolesExists(getRequiredRoles());
34 configureStandardRoles();
35
36 Set<String> workspaceNames = getWorkspaceNames();
37 if (workspaceNames == null || workspaceNames.isEmpty()) {
38 configureJcr(repository, null);
39 } else {
40 for (String workspaceName : workspaceNames)
41 configureJcr(repository, workspaceName);
42 }
43 }
44
45 /** Configures a workspace. */
46 protected void configureJcr(Repository repository, String workspaceName) {
47 Session adminSession;
48 try {
49 adminSession = CmsJcrUtils.openDataAdminSession(repository, workspaceName);
50 } catch (RuntimeException e1) {
51 if (e1.getCause() != null && e1.getCause() instanceof NoSuchWorkspaceException) {
52 Session defaultAdminSession = CmsJcrUtils.openDataAdminSession(repository, null);
53 try {
54 defaultAdminSession.getWorkspace().createWorkspace(workspaceName);
55 log.info("Created JCR workspace " + workspaceName);
56 } catch (RepositoryException e) {
57 throw new IllegalStateException("Cannot create workspace " + workspaceName, e);
58 } finally {
59 Jcr.logout(defaultAdminSession);
60 }
61 adminSession = CmsJcrUtils.openDataAdminSession(repository, workspaceName);
62 } else
63 throw e1;
64 }
65 try {
66 if (prepareJcrTree(adminSession)) {
67 configurePrivileges(adminSession);
68 }
69 } catch (RepositoryException | IOException e) {
70 throw new IllegalStateException("Cannot initialise JCR data layer.", e);
71 } finally {
72 JcrUtils.logoutQuietly(adminSession);
73 }
74 }
75
76 /** To be overridden. */
77 protected Set<String> getWorkspaceNames() {
78 return null;
79 }
80
81 /**
82 * To be overridden in order to programmatically set relationships between
83 * roles. Does nothing by default.
84 */
85 protected void configureStandardRoles() {
86 }
87
88 /**
89 * Creates the base JCR tree structure expected for this app if necessary.
90 *
91 * Expects a clean session ({@link Session#hasPendingChanges()} should return
92 * false) and saves it once the changes have been done. Thus the session can be
93 * rolled back if an exception occurs.
94 *
95 * @return true if something as been updated
96 */
97 public boolean prepareJcrTree(Session adminSession) throws RepositoryException, IOException {
98 return false;
99 }
100
101 /**
102 * Adds app specific default privileges.
103 *
104 * Expects a clean session ({@link Session#hasPendingChanges()} should return
105 * false} and saves it once the changes have been done. Thus the session can be
106 * rolled back if an exception occurs.
107 *
108 * Warning: no check is done and corresponding privileges are always added, so
109 * only call this when necessary
110 */
111 public void configurePrivileges(Session session) throws RepositoryException {
112 }
113
114 /** The system roles that must be available in the system. */
115 protected Set<String> getRequiredRoles() {
116 return new HashSet<>();
117 }
118
119 public void destroy() {
120
121 }
122
123 /*
124 * UTILITIES
125 */
126
127 /** Create these roles as group if they don't exist. */
128 protected void makeSureRolesExists(EnumSet<? extends Distinguished> enumSet) {
129 makeSureRolesExists(Distinguished.enumToDns(enumSet));
130 }
131
132 /** Create these roles as group if they don't exist. */
133 protected void makeSureRolesExists(Set<String> requiredRoles) {
134 if (requiredRoles == null)
135 return;
136 if (getUserAdmin() == null) {
137 log.warn("No user admin service available, cannot make sure that role exists");
138 return;
139 }
140 for (String role : requiredRoles) {
141 Role systemRole = getUserAdmin().getRole(role);
142 if (systemRole == null) {
143 try {
144 getUserTransaction().begin();
145 getUserAdmin().createRole(role, Role.GROUP);
146 getUserTransaction().commit();
147 log.info("Created role " + role);
148 } catch (Exception e) {
149 try {
150 getUserTransaction().rollback();
151 } catch (Exception e1) {
152 // silent
153 }
154 throw new IllegalStateException("Cannot create role " + role, e);
155 }
156 }
157 }
158 }
159
160 /** Add a user or group to a group. */
161 protected void addToGroup(String groupToAddDn, String groupDn) {
162 if (groupToAddDn.contentEquals(groupDn)) {
163 if (log.isTraceEnabled())
164 log.trace("Ignore adding group " + groupDn + " to itself");
165 return;
166 }
167
168 if (getUserAdmin() == null) {
169 log.warn("No user admin service available, cannot add group " + groupToAddDn + " to " + groupDn);
170 return;
171 }
172 Group groupToAdd = (Group) getUserAdmin().getRole(groupToAddDn);
173 if (groupToAdd == null)
174 throw new IllegalArgumentException("Group " + groupToAddDn + " not found");
175 Group group = (Group) getUserAdmin().getRole(groupDn);
176 if (group == null)
177 throw new IllegalArgumentException("Group " + groupDn + " not found");
178 try {
179 getUserTransaction().begin();
180 if (group.addMember(groupToAdd))
181 log.info("Added " + groupToAddDn + " to " + group);
182 getUserTransaction().commit();
183 } catch (Exception e) {
184 try {
185 getUserTransaction().rollback();
186 } catch (Exception e1) {
187 // silent
188 }
189 throw new IllegalStateException("Cannot add " + groupToAddDn + " to " + groupDn);
190 }
191 }
192
193 /*
194 * DEPENDENCY INJECTION
195 */
196 public void setRepository(Repository repository) {
197 this.repository = repository;
198 }
199
200 // public void setUserAdminService(UserAdminService userAdminService) {
201 // this.userAdminService = userAdminService;
202 // }
203
204 protected WorkTransaction getUserTransaction() {
205 return userTransaction;
206 }
207
208 protected UserAdmin getUserAdmin() {
209 return userAdmin;
210 }
211
212 public void setUserAdmin(UserAdmin userAdmin) {
213 this.userAdmin = userAdmin;
214 }
215
216 public void setUserTransaction(WorkTransaction userTransaction) {
217 this.userTransaction = userTransaction;
218 }
219
220 }