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.security.authentication.UserAccessor;
25 import org.wamblee.security.authentication.UserAdministration;
26 import org.wamblee.security.authorization.AbstractAuthorizationService;
27 import org.wamblee.security.authorization.AuthorizationRule;
28 import org.wamblee.security.authorization.AuthorizationService;
29 import org.wamblee.security.authorization.DefaultAuthorizationService;
30 import org.wamblee.security.authorization.Operation;
33 * Authorization service with persistent storage. This is a wrapper for
34 * {@link org.wamblee.security.authorization.DefaultAuthorizationService} which
35 * refreshes the state of the service at certain time intervals.
37 * @author Erik Brakkee
39 public class JpaAuthorizationService implements AuthorizationService {
42 * Authorization service to use.
44 private ComputedValue<AuthorizationService> service;
47 * Hibernate template to use.
49 private EntityManager entityManager;
54 private UserAccessor userAccessor;
57 * User administration.
59 private UserAdministration userAdmin;
62 * Name of the service.
67 * Refresh interval in milliseconds.
69 private final long refreshInterval;
74 private long lastRefreshTime;
77 * Constructs the persistent service.
80 * Name of the service.
81 * @param aEntityManager
86 * User administration.
88 * Whether or not to refresh the state of the service at the
89 * start of every operation.
91 public JpaAuthorizationService(String aName, EntityManager aEntityManager,
92 UserAccessor aAccessor, UserAdministration aUserAdmin,
93 long aRefreshInterval) {
94 entityManager = aEntityManager;
95 refreshInterval = aRefreshInterval;
96 lastRefreshTime = System.currentTimeMillis();
97 userAccessor = aAccessor;
98 userAdmin = aUserAdmin;
100 Computation<AuthorizationService> computation = new Computation<AuthorizationService>() {
102 public boolean isOutOfDate() {
103 long time = System.currentTimeMillis();
104 return service.getCached() == null ||
105 (time - lastRefreshTime) > refreshInterval;
109 public AuthorizationService compute() {
110 AuthorizationService svc = refreshByReload();
111 lastRefreshTime = System.currentTimeMillis();
115 service = new ComputedValue<AuthorizationService>(this, computation);
119 public void setUserAccessor(UserAccessor aUserAccessor) {
120 userAccessor = aUserAccessor;
124 public void setUserAdministration(UserAdministration aUserAdmin) {
125 userAdmin = aUserAdmin;
128 private AuthorizationService refreshByReload() {
129 AuthorizationService svc;
131 svc = entityManager.createNamedQuery(
132 AbstractAuthorizationService.QUERY_FIND_BY_NAME,
133 AbstractAuthorizationService.class).setParameter(
134 DefaultAuthorizationService.NAME_PARAM, name).getSingleResult();
135 svc.setUserAccessor(userAccessor);
136 svc.setUserAdministration(userAdmin);
137 } catch (NonUniqueResultException e) {
138 throw new IllegalArgumentException(
139 "Returned more than one service for name '" + name + "'");
140 } catch (NoResultException e) {
141 svc = new DefaultAuthorizationService(userAccessor, userAdmin, name);
142 entityManager.persist(svc);
151 * org.wamblee.security.authorization.AuthorizationService#isAllowed(java
152 * .lang.Object, org.wamblee.security.authorization.Operation)
154 public boolean isAllowed(Object aResource, Operation aOperation) {
155 return service.get().isAllowed(aResource, aOperation);
161 * @see org.wamblee.security.authorization.AuthorizationService#check(T,
162 * org.wamblee.security.authorization.Operation)
164 public <T> T check(T aResource, Operation aOperation) {
165 return service.get().check(aResource, aOperation);
171 * @see org.wamblee.security.authorization.AuthorizationService#getRules()
173 public AuthorizationRule[] getRules() {
174 return service.get().getRules();
181 * org.wamblee.security.authorization.AuthorizationService#appendRule(org
182 * .wamblee.security.authorization.AuthorizationRule)
184 public void appendRule(AuthorizationRule aRule) {
185 AuthorizationService svc = refreshByReload();
186 svc.appendRule(aRule);
187 // Setting service to null will force reload the next time the
188 // service is used. This deals effectively with the case where the
189 // current transaction would roll back and the change would not have
198 * org.wamblee.security.authorization.AuthorizationService#removeRule(int)
200 public void removeRule(int aIndex) {
201 AuthorizationService svc = refreshByReload();
202 svc.removeRule(aIndex);
210 * org.wamblee.security.authorization.AuthorizationService#insertRuleAfter
211 * (int, org.wamblee.security.authorization.AuthorizationRule)
213 public void insertRuleAfter(int aIndex, AuthorizationRule aRule) {
214 AuthorizationService svc = refreshByReload();
215 svc.insertRuleAfter(aIndex, aRule);