2 * Copyright 2005-2010 the original author or authors.
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.wamblee.security.authorization.jpa;
18 import javax.persistence.EntityManager;
19 import javax.persistence.NoResultException;
20 import javax.persistence.NonUniqueResultException;
22 import org.wamblee.cache.ComputedValue;
23 import org.wamblee.cache.ComputedValue.Computation;
24 import org.wamblee.persistence.JpaMergeSupport;
25 import org.wamblee.security.authentication.UserAccessor;
26 import org.wamblee.security.authentication.UserAdministration;
27 import org.wamblee.security.authorization.AbstractAuthorizationService;
28 import org.wamblee.security.authorization.AbstractAuthorizationRule;
29 import org.wamblee.security.authorization.AuthorizationRule;
30 import org.wamblee.security.authorization.AuthorizationService;
31 import org.wamblee.security.authorization.DefaultAuthorizationService;
32 import org.wamblee.security.authorization.Operation;
35 * Authorization service with persistent storage. This is a wrapper for
36 * {@link org.wamblee.security.authorization.DefaultAuthorizationService} which
37 * refreshes the state of the service at certain time intervals.
39 * @author Erik Brakkee
41 public class JpaAuthorizationService implements AuthorizationService {
44 * Authorization service to use.
46 private ComputedValue<AuthorizationService> service;
49 * Hibernate template to use.
51 private EntityManager entityManager;
56 private UserAccessor userAccessor;
59 * User administration.
61 private UserAdministration userAdmin;
64 * Name of the service.
69 * Refresh interval in milliseconds.
71 private final long refreshInterval;
76 private long lastRefreshTime;
79 * Constructs the persistent service.
82 * Name of the service.
83 * @param aEntityManager
88 * User administration.
90 * Whether or not to refresh the state of the service at the
91 * start of every operation.
93 public JpaAuthorizationService(String aName, EntityManager aEntityManager,
94 UserAccessor aAccessor, UserAdministration aUserAdmin,
95 long aRefreshInterval) {
96 entityManager = aEntityManager;
97 refreshInterval = aRefreshInterval;
98 lastRefreshTime = System.currentTimeMillis();
99 userAccessor = aAccessor;
100 userAdmin = aUserAdmin;
102 Computation<AuthorizationService> computation = new Computation<AuthorizationService>() {
104 public boolean isOutOfDate() {
105 long time = System.currentTimeMillis();
106 return service.getCached() == null ||
107 (time - lastRefreshTime) > refreshInterval;
111 public AuthorizationService compute() {
112 AuthorizationService svc = refreshByReload();
113 lastRefreshTime = System.currentTimeMillis();
117 service = new ComputedValue<AuthorizationService>(this, computation);
121 public void setUserAccessor(UserAccessor aUserAccessor) {
122 userAccessor = aUserAccessor;
126 public void setUserAdministration(UserAdministration aUserAdmin) {
127 userAdmin = aUserAdmin;
130 private AuthorizationService refreshByReload() {
131 AuthorizationService svc;
133 svc = entityManager.createNamedQuery(
134 AbstractAuthorizationService.QUERY_FIND_BY_NAME,
135 AbstractAuthorizationService.class).setParameter(
136 DefaultAuthorizationService.NAME_PARAM, name).getSingleResult();
137 svc.setUserAccessor(userAccessor);
138 svc.setUserAdministration(userAdmin);
139 } catch (NonUniqueResultException e) {
140 throw new IllegalArgumentException(
141 "Returned more than one service for name '" + name + "'");
142 } catch (NoResultException e) {
143 svc = new DefaultAuthorizationService(userAccessor, userAdmin, name);
144 entityManager.persist(svc);
153 * org.wamblee.security.authorization.AuthorizationService#isAllowed(java
154 * .lang.Object, org.wamblee.security.authorization.Operation)
156 public boolean isAllowed(Object aResource, Operation aOperation) {
157 return service.get().isAllowed(aResource, aOperation);
163 * @see org.wamblee.security.authorization.AuthorizationService#check(T,
164 * org.wamblee.security.authorization.Operation)
166 public <T> T check(T aResource, Operation aOperation) {
167 return service.get().check(aResource, aOperation);
173 * @see org.wamblee.security.authorization.AuthorizationService#getRules()
175 public AuthorizationRule[] getRules() {
176 return service.get().getRules();
183 * org.wamblee.security.authorization.AuthorizationService#appendRule(org
184 * .wamblee.security.authorization.AuthorizationRule)
186 public void appendRule(AuthorizationRule aRule) {
187 AuthorizationService svc = refreshByReload();
188 svc.appendRule(aRule);
189 // Setting service to null will force reload the next time the
190 // service is used. This deals effectively with the case where the
191 // current transaction would roll back and the change would not have
200 * org.wamblee.security.authorization.AuthorizationService#removeRule(int)
202 public void removeRule(int aIndex) {
203 AuthorizationService svc = refreshByReload();
204 svc.removeRule(aIndex);
212 * org.wamblee.security.authorization.AuthorizationService#insertRuleAfter
213 * (int, org.wamblee.security.authorization.AuthorizationRule)
215 public void insertRuleAfter(int aIndex, AuthorizationRule aRule) {
216 AuthorizationService svc = refreshByReload();
217 svc.insertRuleAfter(aIndex, aRule);