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.persistence.JpaMergeSupport;
23 import org.wamblee.security.authorization.AbstractAuthorizationService;
24 import org.wamblee.security.authorization.AbstractAuthorizationRule;
25 import org.wamblee.security.authorization.AuthorizationRule;
26 import org.wamblee.security.authorization.AuthorizationService;
27 import org.wamblee.security.authorization.DefaultAuthorizationService;
28 import org.wamblee.security.authorization.Operation;
29 import org.wamblee.usermgt.UserAccessor;
32 * Authorization service with persistent storage. This is a wrapper for
33 * {@link org.wamblee.security.authorization.DefaultAuthorizationService} which
34 * refreshes the state of the service at certain time intervals.
36 * @author Erik Brakkee
38 public class JpaAuthorizationService implements AuthorizationService {
41 * Authorization service to use.
43 private AuthorizationService service;
46 * Hibernate template to use.
48 private EntityManager entityManager;
53 private UserAccessor userAccessor;
56 * Name of the service.
61 * Refresh interval in milliseconds.
63 private final long refreshInterval;
68 private long lastRefreshTime;
71 * Constructs the persistent service.
74 * Name of the service.
75 * @param aEntityManager
80 * Whether or not to refresh the state of the service at the
81 * start of every operation.
83 public JpaAuthorizationService(String aName, EntityManager aEntityManager,
84 UserAccessor aAccessor, long aRefreshInterval) {
85 entityManager = aEntityManager;
86 refreshInterval = aRefreshInterval;
87 lastRefreshTime = System.currentTimeMillis();
88 userAccessor = aAccessor;
93 public void setUserAccessor(UserAccessor aUserAccessor) {
94 userAccessor = aUserAccessor;
98 * Initialize service if needed.
101 private void initialize() {
102 if (service == null) {
103 service = refreshByReload();
107 private AuthorizationService refreshByReload() {
108 AuthorizationService service;
110 service = entityManager.createNamedQuery(
111 AbstractAuthorizationService.QUERY_FIND_BY_NAME,
112 AbstractAuthorizationService.class).setParameter(
113 DefaultAuthorizationService.NAME_PARAM, name).getSingleResult();
114 service.setUserAccessor(userAccessor);
115 } catch (NonUniqueResultException e) {
116 throw new IllegalArgumentException(
117 "Returned more than one service for name '" + name + "'");
118 } catch (NoResultException e) {
119 service = new DefaultAuthorizationService(userAccessor, name);
120 entityManager.persist(service);
129 * org.wamblee.security.authorization.AuthorizationService#isAllowed(java
130 * .lang.Object, org.wamblee.security.authorization.Operation)
132 public boolean isAllowed(Object aResource, Operation aOperation) {
136 return service.isAllowed(aResource, aOperation);
142 * @see org.wamblee.security.authorization.AuthorizationService#check(T,
143 * org.wamblee.security.authorization.Operation)
145 public <T> T check(T aResource, Operation aOperation) {
149 return service.check(aResource, aOperation);
155 * @see org.wamblee.security.authorization.AuthorizationService#getRules()
157 public AuthorizationRule[] getRules() {
161 return service.getRules();
168 * org.wamblee.security.authorization.AuthorizationService#appendRule(org
169 * .wamblee.security.authorization.AuthorizationRule)
171 public void appendRule(AuthorizationRule aRule) {
174 service.appendRule(aRule);
175 save(); // service might still be detached as service is cached.
182 * org.wamblee.security.authorization.AuthorizationService#removeRule(int)
184 public void removeRule(int aIndex) {
187 service.removeRule(aIndex);
188 save(); // service might still be detached as service is cached.
195 * org.wamblee.security.authorization.AuthorizationService#insertRuleAfter
196 * (int, org.wamblee.security.authorization.AuthorizationRule)
198 public void insertRuleAfter(int aIndex, AuthorizationRule aRule) {
201 service.insertRuleAfter(aIndex, aRule);
202 save(); // service might still be detached as service is cached.
206 * Refreshes the state of the service through hibernate.
208 private synchronized void refresh() {
209 long time = System.currentTimeMillis();
211 if ((time - lastRefreshTime) > refreshInterval) {
212 service = refreshByReload();
213 lastRefreshTime = time;
218 * Saves any changes to the service state if necessary.
220 private void save() {
221 AuthorizationService merged = entityManager.merge(service);
222 entityManager.flush();
223 JpaMergeSupport.merge(merged, service);