caf69903d72802d48dd142b4c61411ceb9aba9eb
[utils] / security / src / main / java / org / wamblee / security / authorization / hibernate / PersistentAuthorizationService.java
1 /*
2  * Copyright 2005 the original author or authors.
3  *
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
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16 package org.wamblee.security.authorization.hibernate;
17
18 import org.springframework.orm.hibernate3.HibernateTemplate;
19
20 import org.wamblee.persistence.AbstractPersistent;
21 import org.wamblee.persistence.hibernate.HibernateSupport;
22
23 import org.wamblee.security.authorization.AuthorizationRule;
24 import org.wamblee.security.authorization.AuthorizationService;
25 import org.wamblee.security.authorization.DefaultAuthorizationService;
26 import org.wamblee.security.authorization.Operation;
27
28 import org.wamblee.usermgt.UserAccessor;
29
30 import java.util.List;
31
32
33 /**
34  * Authorization service with persistent storage. This is a wrapper for
35  * {@link org.wamblee.security.authorization.DefaultAuthorizationService}
36  * which refreshes the state of the service at certain time intervals.
37  *
38  * @author Erik Brakkee
39  */
40 public class PersistentAuthorizationService extends AbstractPersistent
41     implements AuthorizationService {
42     /**
43      * Name of query to find the service by name.
44      */
45     private static final String FIND_QUERY = "findAuthorizationServiceByName";
46
47     /**
48      * Name of the query parameter for the service name.
49      */
50     private static final String NAME_PARAM = "name";
51
52     /**
53      * Authorization service to use.
54      */
55     private DefaultAuthorizationService service;
56
57     /**
58      * Hibernate template to use.
59      */
60     private HibernateTemplate template;
61
62     /**
63      * User accessor.
64      */
65     private UserAccessor userAccessor;
66
67     /**
68      * Name of the service.
69      */
70     private String name;
71
72     /**
73      * Refresh interval in milliseconds.
74      */
75     private final long refreshInterval;
76
77     /**
78      * Last refresh time.
79      */
80     private long lastRefreshTime;
81
82 /**
83      * Constructs the persistent service.
84      * 
85      * @param aName
86      *            Name of the service.
87      * @param aTemplate
88      *            Hibernate template for hibernate usage.
89      * @param aAccessor
90      *            User accessor.
91      * @param aRefresh
92      *            Whether or not to refresh the state of the service at the
93      *            start of every operation.
94      */
95     public PersistentAuthorizationService(String aName,
96         HibernateTemplate aTemplate, UserAccessor aAccessor,
97         long aRefreshInterval) {
98         template            = aTemplate;
99         refreshInterval     = aRefreshInterval;
100         lastRefreshTime     = System.currentTimeMillis();
101         userAccessor        = aAccessor;
102         name                = aName;
103     }
104
105     /**
106      * Initialize service if needed.
107      *
108      * @throws IllegalArgumentException DOCUMENT ME!
109      */
110     private void initialize() {
111         if (service == null) {
112             List<DefaultAuthorizationService> result = template
113                 .findByNamedQueryAndNamedParam(FIND_QUERY, NAME_PARAM, name);
114
115             if (result.size() > 1) {
116                 throw new IllegalArgumentException(
117                     "Returned more than one service for name '" + name + "' ("
118                     + result.size() + ")");
119             }
120
121             if (result.size() == 0) {
122                 service = new DefaultAuthorizationService(userAccessor, name);
123                 template.persist(service);
124             } else {
125                 service = result.get(0);
126                 service.setUserAccessor(userAccessor);
127             }
128         }
129     }
130
131     /*
132      * (non-Javadoc)
133      *
134      * @see org.wamblee.security.authorization.AuthorizationService#isAllowed(java.lang.Object,
135      *      org.wamblee.security.authorization.Operation)
136      */
137     /**
138      * DOCUMENT ME!
139      *
140      * @param aResource DOCUMENT ME!
141      * @param aOperation DOCUMENT ME!
142      *
143      * @return DOCUMENT ME!
144      */
145     public boolean isAllowed(Object aResource, Operation aOperation) {
146         initialize();
147         refresh();
148
149         return service.isAllowed(aResource, aOperation);
150     }
151
152     /* (non-Javadoc)
153      * @see org.wamblee.security.authorization.AuthorizationService#check(T, org.wamblee.security.authorization.Operation)
154      */
155     /**
156      * DOCUMENT ME!
157      *
158      * @param <T> DOCUMENT ME!
159      * @param aResource DOCUMENT ME!
160      * @param aOperation DOCUMENT ME!
161      *
162      * @return DOCUMENT ME!
163      */
164     public <T> T check(T aResource, Operation aOperation) {
165         initialize();
166         refresh();
167
168         return service.check(aResource, aOperation);
169     }
170
171     /*
172      * (non-Javadoc)
173      *
174      * @see org.wamblee.security.authorization.AuthorizationService#getRules()
175      */
176     /**
177      * DOCUMENT ME!
178      *
179      * @return DOCUMENT ME!
180      */
181     public AuthorizationRule[] getRules() {
182         initialize();
183         refresh();
184
185         return service.getRules();
186     }
187
188     /*
189      * (non-Javadoc)
190      *
191      * @see org.wamblee.security.authorization.AuthorizationService#appendRule(org.wamblee.security.authorization.AuthorizationRule)
192      */
193     /**
194      * DOCUMENT ME!
195      *
196      * @param aRule DOCUMENT ME!
197      */
198     public void appendRule(AuthorizationRule aRule) {
199         initialize();
200         refresh();
201         service.appendRule(aRule);
202         save();
203     }
204
205     /*
206      * (non-Javadoc)
207      *
208      * @see org.wamblee.security.authorization.AuthorizationService#removeRule(int)
209      */
210     /**
211      * DOCUMENT ME!
212      *
213      * @param aIndex DOCUMENT ME!
214      */
215     public void removeRule(int aIndex) {
216         initialize();
217         refresh();
218         service.removeRule(aIndex);
219         save();
220     }
221
222     /*
223      * (non-Javadoc)
224      *
225      * @see org.wamblee.security.authorization.AuthorizationService#insertRuleAfter(int,
226      *      org.wamblee.security.authorization.AuthorizationRule)
227      */
228     /**
229      * DOCUMENT ME!
230      *
231      * @param aIndex DOCUMENT ME!
232      * @param aRule DOCUMENT ME!
233      */
234     public void insertRuleAfter(int aIndex, AuthorizationRule aRule) {
235         initialize();
236         refresh();
237         service.insertRuleAfter(aIndex, aRule);
238         save();
239     }
240
241     /**
242      * Refreshes the state of the service through hibernate.
243      */
244     private synchronized void refresh() {
245         long time = System.currentTimeMillis();
246
247         if ((time - lastRefreshTime) > refreshInterval) {
248             template.refresh(service);
249             lastRefreshTime = time;
250         }
251     }
252
253     /**
254      * Saves any changes to the service state if necessary.
255      */
256     private void save() {
257         HibernateSupport.merge(template, service);
258     }
259 }