Merge "Formatting applied to aaa-authn-basic"
[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 T poll() {
46         return setAuth(queue.poll());
47     }
48
49     @Override
50     public T element() {
51         return setAuth(queue.element());
52     }
53
54     @Override
55     public T peek() {
56         return setAuth(queue.peek());
57     }
58
59     @Override
60     public int size() {
61         return queue.size();
62     }
63
64     @Override
65     public boolean isEmpty() {
66         return queue.isEmpty();
67     }
68
69     @Override
70     public Iterator<T> iterator() {
71         return new Iterator<T>() {
72             Iterator<SecureData<T>> it = queue.iterator();
73
74             @Override
75             public boolean hasNext() {
76                 return it.hasNext();
77             }
78
79             @Override
80             public T next() {
81                 return it.next().data;
82             }
83
84             @Override
85             public void remove() {
86                 it.remove();
87             }
88         };
89     }
90
91     @Override
92     public Object[] toArray() {
93         return toData().toArray();
94     }
95
96     @SuppressWarnings("hiding")
97     @Override
98     public <T> T[] toArray(T[] a) {
99         return toData().toArray(a);
100     }
101
102     @Override
103     public boolean containsAll(Collection<?> c) {
104         return toData().containsAll(c);
105     }
106
107     @Override
108     public boolean addAll(Collection<? extends T> c) {
109         return queue.addAll(fromData(c));
110     }
111
112     @Override
113     public boolean removeAll(Collection<?> c) {
114         return queue.removeAll(fromData(c));
115     }
116
117     @Override
118     public boolean retainAll(Collection<?> c) {
119         return queue.retainAll(fromData(c));
120     }
121
122     @Override
123     public void clear() {
124         queue.clear();
125     }
126
127     @Override
128     public boolean add(T e) {
129         return queue.add(new SecureData<>(e));
130     }
131
132     @Override
133     public boolean offer(T e) {
134         return queue.offer(new SecureData<>(e));
135     }
136
137     @Override
138     public void put(T e) throws InterruptedException {
139         queue.put(new SecureData<T>(e));
140     }
141
142     @Override
143     public boolean offer(T e, long timeout, TimeUnit unit) throws InterruptedException {
144         return queue.offer(new SecureData<>(e), timeout, unit);
145     }
146
147     @Override
148     public T take() throws InterruptedException {
149         return setAuth(queue.take());
150     }
151
152     @Override
153     public T poll(long timeout, TimeUnit unit) throws InterruptedException {
154         return setAuth(queue.poll(timeout, unit));
155     }
156
157     @Override
158     public int remainingCapacity() {
159         return queue.remainingCapacity();
160     }
161
162     @Override
163     public boolean remove(Object o) {
164         Iterator<SecureData<T>> it = queue.iterator();
165         while (it.hasNext()) {
166             SecureData<T> sd = it.next();
167             if (sd.data.equals(o)) {
168                 return queue.remove(sd);
169             }
170         }
171         return false;
172     }
173
174     @Override
175     public boolean contains(Object o) {
176         Iterator<SecureData<T>> it = queue.iterator();
177         while (it.hasNext()) {
178             SecureData<T> sd = it.next();
179             if (sd.data.equals(o)) {
180                 return true;
181             }
182         }
183         return false;
184     }
185
186     @Override
187     public int drainTo(Collection<? super T> c) {
188         Collection<SecureData<T>> sd = new ArrayList<>();
189         int n = queue.drainTo(sd);
190         c.addAll(toData(sd));
191         return n;
192     }
193
194     @Override
195     public int drainTo(Collection<? super T> c, int maxElements) {
196         Collection<SecureData<T>> sd = new ArrayList<>();
197         int n = queue.drainTo(sd, maxElements);
198         c.addAll(toData(sd));
199         return n;
200     }
201
202     // Rehydrate security context
203     private T setAuth(SecureData<T> i) {
204         AuthenticationManager.instance().set(i.auth);
205         return i.data;
206     }
207
208     // Construct secure data collection from a plain old data collection
209     @SuppressWarnings("unchecked")
210     private Collection<SecureData<T>> fromData(Collection<?> c) {
211         Collection<SecureData<T>> sd = new ArrayList<>(c.size());
212         for (Object d : c) {
213             sd.add((SecureData<T>) new SecureData<>(d));
214         }
215         return sd;
216     }
217
218     // Extract the data portion out from the secure data
219     @SuppressWarnings("unchecked")
220     private Collection<T> toData() {
221         return toData(Arrays.<SecureData<T>> asList(queue.toArray(new SecureData[0])));
222     }
223
224     // Extract the data portion out from the secure data
225     private Collection<T> toData(Collection<SecureData<T>> secureData) {
226         Collection<T> data = new ArrayList<>(secureData.size());
227         Iterator<SecureData<T>> it = secureData.iterator();
228         while (it.hasNext()) {
229             data.add(it.next().data);
230         }
231         return data;
232     }
233
234     // Inject security context
235     public static final class SecureData<T> {
236         private final T data;
237         private final Authentication auth;
238
239         private SecureData(T data) {
240             this.data = data;
241             this.auth = AuthenticationManager.instance().get();
242         }
243
244         @SuppressWarnings("rawtypes")
245         @Override
246         public boolean equals(Object o) {
247             if (o == null) {
248                 return false;
249             }
250             return (o instanceof SecureData) ? data.equals(((SecureData) o).data) : false;
251         }
252
253         @Override
254         public int hashCode() {
255             return data.hashCode();
256         }
257     }
258 }