Merge "Fix issues related to checkstyle enforcement for module aaa-authn"
[aaa.git] / aaa-authn / src / main / java / org / opendaylight / aaa / SecureBlockingQueue.java
1 /*
2  * Copyright (c) 2014 Hewlett-Packard Development Company, L.P. and others.  All rights reserved.
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the Eclipse Public License v1.0 which accompanies this distribution,
6  * and is available at http://www.eclipse.org/legal/epl-v10.html
7  */
8 package org.opendaylight.aaa;
9
10 import java.util.ArrayList;
11 import java.util.Arrays;
12 import java.util.Collection;
13 import java.util.Iterator;
14 import java.util.concurrent.BlockingQueue;
15 import java.util.concurrent.TimeUnit;
16 import org.opendaylight.aaa.api.Authentication;
17
18 /**
19  * A {@link BlockingQueue} decorator with injected security context.
20  *
21  * @author liemmn
22  *
23  * @param <T>
24  *            queue element type
25  */
26 public class SecureBlockingQueue<T> implements BlockingQueue<T> {
27     private final BlockingQueue<SecureData<T>> queue;
28
29     /**
30      * Constructor.
31      *
32      * @param queue
33      *            blocking queue implementation to use
34      */
35     public SecureBlockingQueue(BlockingQueue<SecureData<T>> queue) {
36         this.queue = queue;
37     }
38
39     @Override
40     public T remove() {
41         return setAuth(queue.remove());
42     }
43
44     @Override
45     public boolean remove(Object object) {
46         Iterator<SecureData<T>> it = queue.iterator();
47         while (it.hasNext()) {
48             SecureData<T> sd = it.next();
49             if (sd.data.equals(object)) {
50                 return queue.remove(sd);
51             }
52         }
53         return false;
54     }
55
56
57     @Override
58     public T poll() {
59         return setAuth(queue.poll());
60     }
61
62     @Override
63     public T poll(long timeout, TimeUnit unit) throws InterruptedException {
64         return setAuth(queue.poll(timeout, unit));
65     }
66
67     @Override
68     public T element() {
69         return setAuth(queue.element());
70     }
71
72     @Override
73     public T peek() {
74         return setAuth(queue.peek());
75     }
76
77     @Override
78     public int size() {
79         return queue.size();
80     }
81
82     @Override
83     public boolean isEmpty() {
84         return queue.isEmpty();
85     }
86
87     @Override
88     public Iterator<T> iterator() {
89         return new Iterator<T>() {
90             Iterator<SecureData<T>> it = queue.iterator();
91
92             @Override
93             public boolean hasNext() {
94                 return it.hasNext();
95             }
96
97             @Override
98             public T next() {
99                 return it.next().data;
100             }
101
102             @Override
103             public void remove() {
104                 it.remove();
105             }
106         };
107     }
108
109     @Override
110     public Object[] toArray() {
111         return toData().toArray();
112     }
113
114     @SuppressWarnings("hiding")
115     @Override
116     public <T> T[] toArray(T[] array) {
117         return toData().toArray(array);
118     }
119
120     @Override
121     public boolean containsAll(Collection<?> collection) {
122         return toData().containsAll(collection);
123     }
124
125     @Override
126     public boolean addAll(Collection<? extends T> collection) {
127         return queue.addAll(fromData(collection));
128     }
129
130     @Override
131     public boolean removeAll(Collection<?> collection) {
132         return queue.removeAll(fromData(collection));
133     }
134
135     @Override
136     public boolean retainAll(Collection<?> collection) {
137         return queue.retainAll(fromData(collection));
138     }
139
140     @Override
141     public void clear() {
142         queue.clear();
143     }
144
145     @Override
146     public boolean add(T element) {
147         return queue.add(new SecureData<>(element));
148     }
149
150     @Override
151     public boolean offer(T element) {
152         return queue.offer(new SecureData<>(element));
153     }
154
155     @Override
156     public boolean offer(T element, long timeout, TimeUnit unit) throws InterruptedException {
157         return queue.offer(new SecureData<>(element), timeout, unit);
158     }
159
160     @Override
161     public void put(T element) throws InterruptedException {
162         queue.put(new SecureData<>(element));
163     }
164
165     @Override
166     public T take() throws InterruptedException {
167         return setAuth(queue.take());
168     }
169
170     @Override
171     public int remainingCapacity() {
172         return queue.remainingCapacity();
173     }
174
175     @Override
176     public boolean contains(Object object) {
177         Iterator<SecureData<T>> it = queue.iterator();
178         while (it.hasNext()) {
179             SecureData<T> sd = it.next();
180             if (sd.data.equals(object)) {
181                 return true;
182             }
183         }
184         return false;
185     }
186
187     @Override
188     public int drainTo(Collection<? super T> collection) {
189         Collection<SecureData<T>> sd = new ArrayList<>();
190         int number = queue.drainTo(sd);
191         collection.addAll(toData(sd));
192         return number;
193     }
194
195     @Override
196     public int drainTo(Collection<? super T> collection, int maxElements) {
197         Collection<SecureData<T>> sd = new ArrayList<>();
198         int number = queue.drainTo(sd, maxElements);
199         collection.addAll(toData(sd));
200         return number;
201     }
202
203     // Rehydrate security context
204     private T setAuth(SecureData<T> secureData) {
205         AuthenticationManager.instance().set(secureData.auth);
206         return secureData.data;
207     }
208
209     // Construct secure data collection from a plain old data collection
210     @SuppressWarnings("unchecked")
211     private Collection<SecureData<T>> fromData(Collection<?> collection) {
212         Collection<SecureData<T>> sd = new ArrayList<>(collection.size());
213         for (Object d : collection) {
214             sd.add((SecureData<T>) new SecureData<>(d));
215         }
216         return sd;
217     }
218
219     // Extract the data portion out from the secure data
220     @SuppressWarnings("unchecked")
221     private Collection<T> toData() {
222         return toData(Arrays.<SecureData<T>>asList(queue.toArray(new SecureData[0])));
223     }
224
225     // Extract the data portion out from the secure data
226     private Collection<T> toData(Collection<SecureData<T>> secureData) {
227         Collection<T> data = new ArrayList<>(secureData.size());
228         Iterator<SecureData<T>> it = secureData.iterator();
229         while (it.hasNext()) {
230             data.add(it.next().data);
231         }
232         return data;
233     }
234
235     // Inject security context
236     public static final class SecureData<T> {
237         private final T data;
238         private final Authentication auth;
239
240         private SecureData(T data) {
241             this.data = data;
242             this.auth = AuthenticationManager.instance().get();
243         }
244
245         @SuppressWarnings("rawtypes")
246         @Override
247         public boolean equals(Object object) {
248             if (object == null) {
249                 return false;
250             }
251             return object instanceof SecureData ? data.equals(((SecureData) object).data) : false;
252         }
253
254         @Override
255         public int hashCode() {
256             return data.hashCode();
257         }
258     }
259 }