--- /dev/null
+/*
+ * 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.hibernate;
+
+import org.springframework.orm.hibernate3.HibernateTemplate;
+
+import org.wamblee.persistence.AbstractPersistent;
+import org.wamblee.persistence.hibernate.HibernateSupport;
+
+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;
+
+import java.util.List;
+
+/**
+ * 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 PersistentAuthorizationService extends AbstractPersistent
+ implements AuthorizationService {
+ /**
+ * Name of query to find the service by name.
+ */
+ private static final String FIND_QUERY = "findAuthorizationServiceByName";
+
+ /**
+ * Name of the query parameter for the service name.
+ */
+ private static final String NAME_PARAM = "name";
+
+ /**
+ * Authorization service to use.
+ */
+ private DefaultAuthorizationService service;
+
+ /**
+ * Hibernate template to use.
+ */
+ private HibernateTemplate template;
+
+ /**
+ * 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 aTemplate
+ * Hibernate template for hibernate usage.
+ * @param aAccessor
+ * User accessor.
+ * @param aRefresh
+ * Whether or not to refresh the state of the service at the
+ * start of every operation.
+ */
+ public PersistentAuthorizationService(String aName,
+ HibernateTemplate aTemplate, UserAccessor aAccessor,
+ long aRefreshInterval) {
+ template = aTemplate;
+ refreshInterval = aRefreshInterval;
+ lastRefreshTime = System.currentTimeMillis();
+ userAccessor = aAccessor;
+ name = aName;
+ }
+
+ /**
+ * Initialize service if needed.
+ *
+ */
+ private void initialize() {
+ if (service == null) {
+ List<DefaultAuthorizationService> result = template
+ .findByNamedQueryAndNamedParam(FIND_QUERY, NAME_PARAM, name);
+
+ if (result.size() > 1) {
+ throw new IllegalArgumentException(
+ "Returned more than one service for name '" + name + "' (" +
+ result.size() + ")");
+ }
+
+ if (result.size() == 0) {
+ service = new DefaultAuthorizationService(userAccessor, name);
+ template.persist(service);
+ } else {
+ service = result.get(0);
+ service.setUserAccessor(userAccessor);
+ }
+ }
+ }
+
+ /*
+ * (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> 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) {
+ template.refresh(service);
+ lastRefreshTime = time;
+ }
+ }
+
+ /**
+ * Saves any changes to the service state if necessary.
+ */
+ private void save() {
+ HibernateSupport.merge(template, service);
+ }
+}