/* * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.wamblee.security.authorization.jpa; import javax.persistence.EntityManager; import javax.persistence.NoResultException; import javax.persistence.NonUniqueResultException; import org.wamblee.persistence.JpaMergeSupport; import org.wamblee.security.authorization.AbstractAuthorizationService; import org.wamblee.security.authorization.AbstractAuthorizationRule; import org.wamblee.security.authorization.AuthorizationRule; import org.wamblee.security.authorization.AuthorizationService; import org.wamblee.security.authorization.DefaultAuthorizationService; import org.wamblee.security.authorization.Operation; import org.wamblee.usermgt.UserAccessor; /** * Authorization service with persistent storage. This is a wrapper for * {@link org.wamblee.security.authorization.DefaultAuthorizationService} which * refreshes the state of the service at certain time intervals. * * @author Erik Brakkee */ public class JpaAuthorizationService implements AuthorizationService { /** * Authorization service to use. */ private AuthorizationService service; /** * Hibernate template to use. */ private EntityManager entityManager; /** * User accessor. */ private UserAccessor userAccessor; /** * Name of the service. */ private String name; /** * Refresh interval in milliseconds. */ private final long refreshInterval; /** * Last refresh time. */ private long lastRefreshTime; /** * Constructs the persistent service. * * @param aName * Name of the service. * @param aEntityManager * Entity manager. * @param aAccessor * User accessor. * @param aRefresh * Whether or not to refresh the state of the service at the * start of every operation. */ public JpaAuthorizationService(String aName, EntityManager aEntityManager, UserAccessor aAccessor, long aRefreshInterval) { entityManager = aEntityManager; refreshInterval = aRefreshInterval; lastRefreshTime = System.currentTimeMillis(); userAccessor = aAccessor; name = aName; } @Override public void setUserAccessor(UserAccessor aUserAccessor) { userAccessor = aUserAccessor; } /** * Initialize service if needed. * */ private void initialize() { if (service == null) { refreshByReload(); } } private void refreshByReload() { try { service = entityManager.createNamedQuery( AbstractAuthorizationService.QUERY_FIND_BY_NAME, AbstractAuthorizationService.class).setParameter( AbstractAuthorizationService.NAME_PARAM, name).getSingleResult(); service.setUserAccessor(userAccessor); } catch (NonUniqueResultException e) { throw new IllegalArgumentException( "Returned more than one service for name '" + name + "'"); } catch (NoResultException e) { service = new DefaultAuthorizationService(userAccessor, name); entityManager.persist(service); } } /* * (non-Javadoc) * * @see * org.wamblee.security.authorization.AuthorizationService#isAllowed(java * .lang.Object, org.wamblee.security.authorization.Operation) */ public boolean isAllowed(Object aResource, Operation aOperation) { initialize(); refresh(); return service.isAllowed(aResource, aOperation); } /* * (non-Javadoc) * * @see org.wamblee.security.authorization.AuthorizationService#check(T, * org.wamblee.security.authorization.Operation) */ public T check(T aResource, Operation aOperation) { initialize(); refresh(); return service.check(aResource, aOperation); } /* * (non-Javadoc) * * @see org.wamblee.security.authorization.AuthorizationService#getRules() */ public AuthorizationRule[] getRules() { initialize(); refresh(); return service.getRules(); } /* * (non-Javadoc) * * @see * org.wamblee.security.authorization.AuthorizationService#appendRule(org * .wamblee.security.authorization.AuthorizationRule) */ public void appendRule(AuthorizationRule aRule) { initialize(); refresh(); service.appendRule(aRule); save(); } /* * (non-Javadoc) * * @see * org.wamblee.security.authorization.AuthorizationService#removeRule(int) */ public void removeRule(int aIndex) { initialize(); refresh(); service.removeRule(aIndex); save(); } /* * (non-Javadoc) * * @see * org.wamblee.security.authorization.AuthorizationService#insertRuleAfter * (int, org.wamblee.security.authorization.AuthorizationRule) */ public void insertRuleAfter(int aIndex, AuthorizationRule aRule) { initialize(); refresh(); service.insertRuleAfter(aIndex, aRule); save(); } /** * Refreshes the state of the service through hibernate. */ private synchronized void refresh() { long time = System.currentTimeMillis(); if ((time - lastRefreshTime) > refreshInterval) { refreshByReload(); lastRefreshTime = time; } } /** * Saves any changes to the service state if necessary. */ private void save() { AuthorizationService merged = entityManager.merge(service); entityManager.flush(); JpaMergeSupport.merge(merged, service); } }